About modifying exists model's vertex position & GeomVertexRewriter issue

Hi, all, right now I load a model from .bam file, and I want to modify its vertex position on the runtime, so I use GeomVertexRewriter function, but it came with this error:

vertex = GeomVertexRewriter(vdata, ‘vertex’)
TypeError: Arguments must match:
GeomVertexRewriter()
GeomVertexRewriter(GeomVertexArrayData array_data)
GeomVertexRewriter(GeomVertexData vertex_data)
GeomVertexRewriter(const GeomVertexRewriter copy)
GeomVertexRewriter(Thread current_thread)
GeomVertexRewriter(GeomVertexArrayData array_data, int column, Thread current_thread)
GeomVertexRewriter(GeomVertexData vertex_data, const InternalName name, Thread current_thread)
GeomVertexRewriter(GeomVertexArrayData array_data, Thread current_thread)
GeomVertexRewriter(GeomVertexData vertex_data, Thread current_thread)

I basically write code using panda3d manual, and let me put the code samples here:

indent preformatted text by 4 spaces

model = self.loader.load_model("somemodel.bam")
geomNodeCollection = model.findAllMatches('**/+GeomNode')
for nodePath in geomNodeCollection:
    geomNode = nodePath.node()
    geom = geomNode.getGeom(0)
    vdata = geom.getVertexData()
    vertex = GeomVertexRewriter(vdata, 'vertex')
    while not vertex.isAtEnd():
        vertex.setData3(0.0, 0.0, 0.0)

I was blocked in this issue for a while, please give me any hints if you have any idea, thanks.

I suspect that the problem is that the “getVertexData” method returns a const reference–that is, one that may not be changed. GeomVertexRewriter is presumably expecting a non-const reference, one whose data it can alter.

If you want to modify the vertex-data that you’re storing in “vdata”, I recommend trying the “modifyVertexData” method, instead–I believe that this returns a non-const, and thus modifiable, reference!

2 Likes

你好, welcome to the Panda3D community :slight_smile: !

As @Thaumaturge pointed out, you should indeed call Geom.modify_vertex_data(). But first you also need to call modify_geom(0) on your GeomNode instead of getGeom(0). More about that on this manual page.

So your code sample would look something like this:

model = self.loader.load_model("somemodel.bam")
geomNodeCollection = model.findAllMatches('**/+GeomNode')
for nodePath in geomNodeCollection:
    geomNode = nodePath.node()
    geom = geomNode.modify_geom(0)
    vdata = geom.modify_vertex_data()
    vertex = GeomVertexRewriter(vdata, 'vertex')
    while not vertex.isAtEnd():
        vertex.setData3(0.0, 0.0, 0.0)

If you want to make your code as efficient as possible, it is recommended to use memoryviews instead of GeomVertexReader/Writer/Rewriter. Although this is not (yet) explained in the manual, I have made some code samples that you can study to get familiar with how that works.

Also, in case you wanted to offset (translate) the vertex positions instead of setting them to specific coordinates, it would be a lot better to call GeomVertexData.transform_vertices, or even Geom.transform_vertices.

2 Likes