I am trying to render a gltf model with ash (vulkan) in rust.
I sent all my data to the gpu and I am seeing this:
Naturally my suspicion is that the normal data is wrong. So I checked with renderdoc:
Those seem ok, maybe the attributes are wrong?
All those normals seem like they add to 1, should be fine. Maybe my pipeline is wrong?
Seems like the correct format and binding (I am sending 3 buffers and binding one to binding 0, one to 1 and the last to 2, binding 1 has the normals).
The only thing I find that is weird is, if I go to the vertex input pipeline stage see the buffers:
This is what the buffer at index 1 shows:
This does not happen for the buffer at index 0 (positions) which also render properly. So Whatever is causing the normals to show up as hex codes here is likely the cause of the bug. But i have no idea why this is happening. As far as I can see the pipeline and buffer were all set properly.
You presumably want to use one separate buffer for each vertex attribute (aka non-interleaved vertex buffer, SoA),
but your VkVertexInputAttributeDescription::offset values [0, 12, 24] is what you would use for one vertex buffer interleaving all attributes (provided that their binding values point to one and the same VkVertexInputBindingDescription).
e.g.
// Interleaved:
// Buffer 0: |Position: R32G32B32_FLOAT, Normal: R32G32B32_FLOAT, Uv: R32G32B32_FLOAT|, * vertex count
VkVertexInputBindingDescription {
.binding = 0,
.stride = 12 * 3, // 3 `R32G32B32_FLOAT`s !
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
};
// All attributes in the same `binding` == `0`
VkVertexInputAttributeDescription[3] {
{
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 0 // [0, 11] portion
},
{
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 12 // [12, 23] portion
},
{
.location = 2,
.binding = 0,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 24 // [24, 35] portion
}
};
Your VkVertexInputBindingDescription[1].stride == 12 tells Vulkan that your vertex buffer 1 uses 12 bytes for each vertex, and your VkVertexInputAttributeDescription[1].offset == 12 says the normal value is at offset 12, which is out of bounds.
Same deal with your VkVertexInputAttributeDescription[2].offset == 24 overstepping (by a large amount) VkVertexInputBindingDescription[2].stride == 12.
For using one tightly-packed buffer for each vertex attribute, you need to correctly set your VkVertexInputAttributeDescription[n].offset values to 0, which looks something like:
// Non-interleaved:
// Buffer 0: |Position: R32G32B32_FLOAT|, * vertex count
// Buffer 1: |Normal: R32G32B32_FLOAT|, * vertex count
// Buffer 2: |Uv: R32G32B32_FLOAT|, * vertex count
VkVertexInputBindingDescription[3] {
{
.binding = 0,
.stride = 12,
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
},
{
.binding = 1,
.stride = 12,
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
},
{
.binding = 2,
.stride = 12,
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
}
};
// Each attribute in its own `binding` == `location`
VkVertexInputAttributeDescription[3] {
{
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 0 // Whole [0, 11]
},
{
.location = 1,
.binding = 1,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 0 // Whole [0, 11]
},
{
.location = 2,
.binding = 2,
.format = VK_FORMAT_R32G32G32_SFLOAT,
.offset = 0 // Whole [0, 11]
}
};
Worth noting is the comment line // vertex stride 12 less than total data fetched 24 generated by RenderDoc in the Buffer Format section, and how it does so.
It detects when your vertex attribute description oversteps its binding description's stride:
if(i + 1 == attrs.size())
{
// for the last attribute, ensure the total size doesn't overlap stride
if(attrs[i].byteOffset + cursz > stride && stride > 0)
return tr("// vertex stride %1 less than total data fetched %2")
.arg(stride)
.arg(attrs[i].byteOffset + cursz);
}
Related
I am connecting to a fanuc cnc machine with Python using a C library. I learned C++ about 20 years ago (haven't used it since) and am not super strong in Python so I'm struggling with data types.
I have data coming from the c library in the following format
I am using the following code to read it:
cnc_ids = (ctypes.c_uint32 * 11)()
ret = focas.cnc_rddynamic2(libh, 1, 44, cnc_ids)
if ret != 0:
raise Exception(f"Failed to read cnc id! ({ret})")
for i in range(11):
print(f"{i}: {cnc_ids[i]}")
If all of the pieces of data were a length of 4 bytes this would be easy, but the first two are only 2 bytes each.
I imagine I could just split the first 4 byte group into two with some extra code, but I will be interfacing about 300 different functions, all with similar structures so it will be a recurring issue. Some of these functions will have several different lengths of data that need to be processed.
What is the best way to process this data?
My end goal is to output the data in a json format that will be used for an api within flask.
Additional info - The typedef is also provided. If there is just a way I can use that directly that would be awesome. Below is the example they give for this function.
typedef struct odbdy2 {
short dummy ; /* not used */
short axis ; /* axis number */
long alarm ; /* alarm status */
long prgnum ; /* current program number */
long prgmnum ; /* main program number */
long seqnum ; /* current sequence number */
long actf ; /* actual feedrate */
long acts ; /* actual spindle speed */
union {
struct {
long absolute[MAX_AXIS] ; /* absolute */
long machine[MAX_AXIS] ; /* machine */
long relative[MAX_AXIS] ; /* relative */
long distance[MAX_AXIS] ; /* distance to go */
} faxis ; /* In case of all axes */
struct {
long absolute ; /* absolute */
long machine ; /* machine */
long relative ; /* relative */
long distance ; /* distance to go */
} oaxis ; /* In case of 1 axis */
} pos ;
} ODBDY2 ; /* MAX_AXIS is the maximum controlled axes. */
With ctypes, the structure can be declared and used directly. If you receive the data as a buffer of 32-bit values, you can cast that buffer into the structure as shown below:
import ctypes as ct
MAX_AXIS = 3 # Not provided by OP, guess...
class FAXIS(ct.Structure):
_fields_ = (('absolute', ct.c_long * MAX_AXIS),
('machine', ct.c_long * MAX_AXIS),
('relative', ct.c_long * MAX_AXIS),
('distance', ct.c_long * MAX_AXIS))
def __repr__(self):
return f'FAXIS({list(self.absolute)}, {list(self.machine)}, {list(self.relative)}, {list(self.distance)})'
class OAXIS(ct.Structure):
_fields_ = (('absolute', ct.c_long),
('machine', ct.c_long),
('relative', ct.c_long),
('distance', ct.c_long))
def __repr__(self):
return f'OAXIS({self.absolute}, {self.machine}, {self.relative}, {self.distance})'
class POS(ct.Union):
_fields_ = (('faxis', FAXIS),
('oaxis', OAXIS))
def __repr__(self):
return f'POS({self.faxis!r}, {self.oaxis!r})'
class ODBDY2(ct.Structure):
_fields_ = (('dummy', ct.c_short),
('axis', ct.c_short),
('alarm', ct.c_long),
('prgnum', ct.c_long),
('prgmnum', ct.c_long),
('seqnum', ct.c_long),
('actf', ct.c_long),
('acts', ct.c_long),
('pos', POS))
def __repr__(self):
return f'ODBDY2({self.dummy}, {self.axis}, {self.alarm}, {self.prgnum}, {self.prgmnum}, {self.seqnum}, {self.actf}, {self.acts}, {self.pos!r})'
cnc_one_axis = (ct.c_uint32 * 11)(1,2,3,4,5,6,7,8,9,10,11)
cnc_all_axis = (ct.c_uint32 * 19)(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
p = ct.pointer(cnc_all_axis)
data = ct.cast(p, ct.POINTER(ODBDY2))
print(data.contents)
p = ct.pointer(cnc_one_axis)
data = ct.cast(p, ct.POINTER(ODBDY2)) # Notice only OAXIS has valid data
print(data.contents)
Output:
ODBDY2(1, 0, 2, 3, 4, 5, 6, 7, POS(FAXIS([8, 9, 10], [11, 12, 13], [14, 15, 16], [17, 18, 19]), OAXIS(8, 9, 10, 11)))
ODBDY2(1, 0, 2, 3, 4, 5, 6, 7, POS(FAXIS([8, 9, 10], [11, 0, 1], [0, -1838440016, 32762], [1, 0, -1]), OAXIS(8, 9, 10, 11)))
I want to make a table in Document Word using python-docx but the width of the table is always max to the ruler. How can I customize this?
My code:
def table_columns(text, my_rows):
row = table.rows[0].cells
paragraph = row[my_rows].add_paragraph()
get_paragraph = paragraph.add_run(text)
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
get_paragraph.bold = True
font = get_paragraph.font
font.size= Pt(10)
table = doc.add_table(rows = 1, cols = 5, style = 'Table Grid')
columns_width = {
0: 2,
1: 35,
2: 35,
3: 42,
4: 170
}
for column_idx in range(len(table.columns)):
table.cell(0, column_idx).width = Cm(columns_width[column_idx])
for rows_idx in range(len(table.rows)):
table.rows[rows_idx].height = Cm(1.25)
columns_names = {
0: 'NO',
1: 'VALUE1',
2: 'VALUE2',
3: 'VALUE3',
4: 'VALUE4'
}
for column_idx in range(len(table.columns)):
table_columns(columns_names[column_idx], column_idx)
I also change the columns_width but give the same result.
Here are the results and what I want to make to:
Thanks for your help.
Cell width is what matters here. You are using:
columns_width = {
0: 2,
1: 35,
2: 35,
3: 42,
4: 170
}
table.cell(0, column_idx).width = Cm(columns_width[column_idx])
to set the cell widths, which is fine, but you are using large Cm() (centimeter) lengths to do it. For example, 170 cm is 1.7 meters.
If you use Pt() instead or possibly Mm() I think you'll get better results.
I'm at the last stages of completing my program's transition from Tkinter to Gtk. The last step is updating the ListStore in an efficient manner. So far, what I'm trying is working...but for only about 15-120 seconds before it crashes (error code is 139; sometimes a coredump with no other message, sometimes a "Warning: corrupted double-linked list detected"). While it's running, top reports less than 100 MB of RAM in use.
The ListStore contains 51 rows with 25 columns, created as follows:
def init_ListStore():
# initialize the main ListStore database
for symbol in cbp_symbols.keys():
name = cbp_symbols[symbol]['name']
row = [symbol, name, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
liststore1.append(row)
treeview1.set_model(liststore1)
cell = Gtk.CellRendererText()
columns = list(my_vars['liststore_main']['column_data'].keys())
for i in range(liststore1.get_n_columns()):
treeviewcolumn = Gtk.TreeViewColumn(columns[i])
treeview1.append_column(treeviewcolumn)
treeviewcolumn.pack_start(cell, True)
treeviewcolumn.add_attribute(cell, "text", i)
After this is done, I do the following (3) steps:
Update my account information (token balances), get a new message from the websocket (stored as dictionary), update the new info, on a cell-to-cell basis, something like:
liststore1[row][col.index('Open')] = float(ticker_data["open_24h"])
liststore1[row][col.index('Last')] = float(ticker_data["price"])
liststore1[row][col.index('Low')] = float(ticker_data["low_24h"])
liststore1[row][col.index('High')] = float(ticker_data["high_24h"])
liststore1[row][col.index('Volume')] = float(ticker_data["volume_24h"])
I would like to be able to edit/replace the entire row in one shot; the above seems slow and burdensome. Once the initial creation/updates are done, everything is being done with the same function (there are about 20 total updates to be made with each message).
UPDATE #1: this time I got a more definitive error. The problem is in the lib/python3.8/site-packages/gi/overrides/Gtk.py module, line 1680:
if GTK2 or GTK3:
_Gtk_main_quit = Gtk.main_quit
#override(Gtk.main_quit)
def main_quit(*args):
_Gtk_main_quit()
_Gtk_main = Gtk.main
#override(Gtk.main)
def main(*args, **kwargs):
with register_sigint_fallback(Gtk.main_quit):
with wakeup_on_signal():
return _Gtk_main(*args, **kwargs) << this line
UPDATE #2: I think this is related to multithread locking, but I don't have a clue how that works (module is imported by the websocket client, not by me). I did try to apply a lock on the main function that parses the incoming socket message, but it didn't help. I do know that if I run the program without the Gtk window active, it never crashes.
Finally got this working. The trick was to use Gtk.TreeIter to reference the current row, then update the entire row in one shot:
titer = liststore1.get_iter(row)
my_columns = [
df.columns.get_loc('Last') + 1,
df.columns.get_loc('Open') + 1,
df.columns.get_loc('Change') + 1,
df.columns.get_loc('Change %') + 1,
df.columns.get_loc('Low') + 1,
df.columns.get_loc('High') + 1,
df.columns.get_loc('Value') + 1,
df.columns.get_loc('Val Open') + 1,
df.columns.get_loc('Port %') + 1,
df.columns.get_loc('Cost Basis') + 1,
df.columns.get_loc('CB Change') + 1,
df.columns.get_loc('Value') + 1,
df.columns.get_loc('Val Open') + 1,
df.columns.get_loc('Profit') + 1,
df.columns.get_loc('Volume') + 1,
df.columns.get_loc('30d Avg') + 1,
df.columns.get_loc('Vol Act %') + 1,
df.columns.get_loc('Trade Val') + 1
]
my_data = [
df.at[row, 'Last'],
df.at[row, 'Open'],
df.at[row, 'Change'],
df.at[row, 'Change %'],
df.at[row, 'Low'],
df.at[row, 'High'],
df.at[row, 'Value'],
df.at[row, 'Val Open'],
df.at[row, 'Port %'],
df.at[row, 'Cost Basis'],
df.at[row, 'CB Change'],
df.at[row, 'Value'],
df.at[row, 'Val Open'],
df.at[row, 'Profit'],
df.at[row, 'Volume'],
df.at[row, '30d Avg'],
df.at[row, 'Vol Act %'],
df.at[row, 'Trade Val']
]
liststore1.set(titer, my_columns, my_data)
I know this code needs to be streamlined, but I tend to get something working first, then simplify/streamline afterwards.
I am making a python program that converts numbers to binary with a tkinter GUI. When using e.insert on a entry it will return a normal string:
0101010011
as
[0, 1, 0, 1...]
The function which converts a number to binary. I am aware the bin() alternative exists, I just wanted to create my own.
def dec2bin(decnum):
binarylist = []
while (decnum > 0):
binarylist.append(decnum % 2)
decnum = decnum // 2
binarylist.reverse()
binarylist = str(binarylist)
return "".join(binarylist)
The function that is called when a button in the tkinter gui is pressed which is intended to replace one of the entry box's text with the binary output.
def convert():
decimal = entrydec.get()
decimal = int(decimal)
entrybin.delete(0, END)
entrybin.insert(0, dec2bin(decimal))
I expect the output of 010101, but the actual output is [0, 1, 0, 1, 0, 1]
You can't use str() on list - str([0, 1, 0, 0]) to get list with strings - ["0", "1", "0", "0"]
You can use list comprehension:
binarylist = [str(x) for x in binarylist]
or map() :
binarylist = map(str, binarylist)
Or you have to convert numbers 0 ,1 to string when you add to list:
binarylist.append( str(decnum % 2) )
And later you can use join()
def dec2bin(decnum):
binarylist = []
while (decnum > 0):
binarylist.append( str(decnum % 2) ) # <-- use str()
decnum = decnum // 2
binarylist.reverse()
#binarylist = str(binarylist) # <-- remove it
return "".join(binarylist)
dec2bin(12)
Result:
"1100"
I'm using Fit.Polynomial to fit my data and show by graph, and all works great, but I couldn't find way to present my Y-function to any order. If the function is order 2 so I want it to be presents as y=ax^2+bx+c, and if the order is 3 so function would be y=ax^3+bx^2+cx+d.
Is there any way to do it?
Use Polynomial.Fit which returns Polynomial instead of Fit.Polynomial which returns double[].
var x = new double[] { 1, 2, 3 };
var y = new double[] { 2, 5, 9 };
Console.WriteLine("Fit.Polynomial");
double[] #double = Fit.Polynomial(x, y, 2);
Console.WriteLine(#double);
Console.WriteLine(string.Join(", ", #double));
Console.WriteLine("\nPolynomial.Fit");
Polynomial polynomial = Polynomial.Fit(x, y, 2);
Console.WriteLine(polynomial);
Console.WriteLine("\nPolynomial.Fit");
Polynomial polynomial = Polynomial.Fit(x, y, 2);
Console.WriteLine(polynomial);
Gives
Fit.Polynomial
System.Double[]
0, 1.5, 0.500000000000001
Polynomial.Fit
1.5x + 0.500000000000001x^2