Hi to all,
I’ve run into a small issue when deleting vertices from panda3d’s vertex table with the following process:
-
Create 2 geoms and fill them up with the relevant primitive and vertex data.
-
Add these 2 geoms to a single geomNode.
-
Create the nodepath from the geomNode.
-
Attempt to remove the 4 primitives [numbers: 1,2,3,4] from the first geom as well as delete the vertex data they reference in the relevant vertex table.
-
Since data was removed from the relevant vertex table, renumber the remaining referenced vertex data in the remaining primitives within both geoms in the entire geomNode.
-
Here is the code performing the above-mentioned process, just copy paste and run to test it:
from direct.showbase.ShowBase import ShowBase
from panda3d.core import *
import copy
class run_me(ShowBase):
def __init__(self):
ShowBase.__init__(self)
self.DrawBox()
def myNormalize(self,myVec):
myVec.normalize()
return myVec
def DrawBox(self):
#administrative stuff...
array = GeomVertexArrayFormat()
array.addColumn(InternalName.make('vertex'), 3,Geom.NTFloat32, Geom.CPoint)
array.addColumn(InternalName.make('texcoord'), 2,Geom.NTFloat32, Geom.CTexcoord)
array.addColumn(InternalName.make('normal'), 3,Geom.NTFloat32, Geom.CNormal)
array.addColumn(InternalName.make('color'), 4,Geom.NTFloat32, Geom.CColor)
format = GeomVertexFormat()
format.addArray(array)
format = GeomVertexFormat.registerFormat(format)
self.vdata = GeomVertexData('name', format, Geom.UHStatic)
self.vertex = GeomVertexWriter(self.vdata, 'vertex')
self.normal = GeomVertexWriter(self.vdata, 'normal')
self.color = GeomVertexWriter(self.vdata, 'color')
self.texcoord = GeomVertexWriter(self.vdata, 'texcoord')
counter=0
faces=[]
#start Geom 1's data:
p1=LVecBase3f(0, 0, 0)
p2=LVecBase3f(60, 0, 0)
p3=LVecBase3f(0, 256, 0)
p4=LVecBase3f(60, 256, 0)
faces.append([p1,p2,p3,p4])
p5=LVecBase3f(60, 0, 0)
p6=LVecBase3f(72, 0, 0)
p7=LVecBase3f(60, 144, 0)
p8=LVecBase3f(72, 144, 0)
faces.append([p5,p6,p7,p8])
p9=LVecBase3f(72, 0, 0)
p10=LVecBase3f(84, 0, 0)
p11=LVecBase3f(72, 144, 0)
p12=LVecBase3f(84, 144, 0)
faces.append([p9,p10,p11,p12])
p13=LVecBase3f(60, 160, 0)
p14=LVecBase3f(72, 160, 0)
p15=LVecBase3f(60, 256, 0)
p16=LVecBase3f(72, 256, 0)
faces.append([p13,p14,p15,p16])
p17=LVecBase3f(72, 160, 0)
p18=LVecBase3f(84, 160, 0)
p19=LVecBase3f(72, 256, 0)
p20=LVecBase3f(84, 256, 0)
faces.append([p17,p18,p19,p20])
p21=LVecBase3f(84, 0, 0)
p22=LVecBase3f(256, 0, 0)
p23=LVecBase3f(84, 256, 0)
p24=LVecBase3f(256, 256, 0)
faces.append([p21,p22,p23,p24])
#start Geom 2's data:
p25=LVecBase3f(60, 160, 0)
p26=LVecBase3f(60, 144, 0)
p27=LVecBase3f(64, 156, -4)
p28=LVecBase3f(64, 148, -4)
faces.append([p25,p26,p27,p28])
p29=LVecBase3f(64, 156, -4)
p30=LVecBase3f(80, 156, -4)
p31=LVecBase3f(60, 160, 0)
p32=LVecBase3f(84, 160, 0)
faces.append([p29,p30,p31,p32])
p33=LVecBase3f(64, 148, -4)
p34=LVecBase3f(80, 148, -4)
p35=LVecBase3f(60, 144, 0)
p36=LVecBase3f(84, 144, 0)
faces.append([p33,p34,p35,p36])
p37=LVecBase3f(84, 160, 0)
p38=LVecBase3f(84, 144, 0)
p39=LVecBase3f(80, 156, -4)
p40=LVecBase3f(80, 148, -4)
faces.append([p37,p38,p39,p40])
p41=LVecBase3f(80, 156, -4)
p42=LVecBase3f(76, 156, -4)
p43=LVecBase3f(80, 148, -4)
p44=LVecBase3f(76, 148, -4)
faces.append([p41,p42,p43,p44])
p45=LVecBase3f(64, 148, -4)
p46=LVecBase3f(76, 148, -4)
p47=LVecBase3f(64, 156, -4)
p48=LVecBase3f(76, 156, -4)
faces.append([p45,p46,p47,p48])
#draw both geoms:
node = GeomNode("GeomBox")
numverz=0
geom1=Geom(self.vdata)
geom2=Geom(self.vdata)
for array2 in faces:
prim = GeomTriangles(Geom.UHStatic)
self.draw_faces(prim,array2,counter)
prim.closePrimitive()
if(numverz>=6):
geom2.addPrimitive(prim)
else:
geom1.addPrimitive(prim)
counter+=4
numverz+=1
node.addGeom(geom1)
node.addGeom(geom2)
self.nodePathaqq = render.attachNewNode(node)
self.nodePathaqq.setTransparency(TransparencyAttrib.MAlpha,1)
self.nodePathaqq.setTwoSided(True)
pandafile = Filename.fromOsSpecific("world_textures/desert.png")
myTexture1=loader.loadTexture(pandafile)
self.nodePathaqq.setAttrib(ShadeModelAttrib.make(ShadeModelAttrib.MSmooth))
newTS = TextureStage('1')
self.nodePathaqq.setTexture(newTS,myTexture1)
#now, attempt to remove the four first primitives(faces)
#from the first geom:
gnode=self.nodePathaqq.node()
geom=gnode.modifyGeom(0)
gotVertices=[]
#first, store the vertices that these four primitives
#reference in the vertex table:
p1=geom.modifyPrimitive(1)
p2=geom.modifyPrimitive(2)
p3=geom.modifyPrimitive(3)
p4=geom.modifyPrimitive(4)
for indd in p1.getVertexList():
if(gotVertices.count(indd)==0):
gotVertices.append(indd)
for indd in p2.getVertexList():
if(gotVertices.count(indd)==0):
gotVertices.append(indd)
for indd in p3.getVertexList():
if(gotVertices.count(indd)==0):
gotVertices.append(indd)
for indd in p4.getVertexList():
if(gotVertices.count(indd)==0):
gotVertices.append(indd)
#then, remove the four primitives themselves:
geom.removePrimitive(1)
geom.removePrimitive(1)
geom.removePrimitive(1)
geom.removePrimitive(1)
bufferDat=[]
bufferDat=copy.copy(gotVertices)
#show the primitive and vertex data for the second geom
#before deleting the relevant vertices:
vdata = geom.modifyVertexData()
vertexReader = GeomVertexReader(vdata, 'vertex')
print "Pre-delete geom-data:\n"
geom2=gnode.modifyGeom(1)
for primz in xrange(geom2.getNumPrimitives()):
primitive=geom2.modifyPrimitive(primz)
print "Prim ",primz,": \n"
seen=[]
for vnm in primitive.getVertexList():
vertexReader.setRow(vnm)
v1 = vertexReader.getData3f()
if(seen.count(v1)==0):
print "V: ",vnm,v1
seen.append(v1)
del seen[:]
#remove the vertices from the vertex-table:
vertexArray=vdata.modifyArray(0)
vertexArrayModder=GeomVertexWriter(vertexArray,0)
vertexArrayHandle=vertexArray.modifyHandle()
vertexArrayFormat=vertexArrayHandle.getArrayFormat()
length=vertexArrayFormat.getStride()
for indiii in xrange(len(gotVertices)):
vert=gotVertices[indiii]
start=vert
vertexArrayHandle.setSubdata(start*length, length, '')
#renumber:
for indiii2 in xrange(len(gotVertices)):
if(gotVertices[indiii2]>vert):
gotVertices[indiii2]-=1
#renumber the relevant data in the primitive tables:
for i in range(2):
#get the current geom:
geom = gnode.modifyGeom(i)
#go through the primitives in this geom:
indoo=0
lenz=geom.getNumPrimitives()
while indoo<lenz:
primitive=geom.modifyPrimitive(indoo)
vertexArrayData=primitive.modifyVertices()
primitiveArrayModder=GeomVertexWriter(vertexArrayData,0)
primitiveArrayReader=GeomVertexReader(vertexArrayData,0)
while not primitiveArrayReader.isAtEnd():
rowz=primitiveArrayReader.getData1i()
numValz=0
numValz=rowz
numgret=0
for indiii2 in xrange(len(bufferDat)):
if(numValz>bufferDat[indiii2]):
numgret+=1
numValz-=numgret
primitiveArrayModder.setData1i(numValz)
indoo+=1
#show the data for the second geom after the deletion and
#renumbering process is done:
vertexReader = GeomVertexReader(vdata, 'vertex')
print "Post-delete geom-data:\n"
geom2=gnode.modifyGeom(1)
for primz in xrange(geom2.getNumPrimitives()):
primitive=geom2.modifyPrimitive(primz)
print "Prim ",primz,": \n"
seen=[]
for vnm in primitive.getVertexList():
vertexReader.setRow(vnm)
v1 = vertexReader.getData3f()
if(seen.count(v1)==0):
print "V: ",vnm,v1
seen.append(v1)
del seen[:]
def draw_faces(self,prim_dat,array_sent,numbr):
#1.vertex:
k1=1
self.vertex.addData3f(array_sent[0].x,array_sent[0].y, array_sent[0].z)
self.normal.addData3f(self.myNormalize(Vec3(2*array_sent[0].x-1,2*array_sent[0].y-1,2*array_sent[0].z-1)))
randi=0.8
self.color.addData4f(k1, k1, k1, 1)
self.texcoord.addData2f(1, 0)
#2.vertex:
k2=1
self.vertex.addData3f(array_sent[1].x,array_sent[1].y, array_sent[1].z)
self.normal.addData3f(self.myNormalize(Vec3(2*array_sent[1].x-1,2*array_sent[1].y-1,2*array_sent[1].z-1)))
self.color.addData4f(k2, k2, k2, 1)
self.texcoord.addData2f(1, 1)
#3.vertex:
k3=1
self.vertex.addData3f(array_sent[2].x,array_sent[2].y, array_sent[2].z)
self.normal.addData3f(self.myNormalize(Vec3(2*array_sent[2].x-1,2*array_sent[2].y-1,2*array_sent[2].z-1)))
self.color.addData4f(k3, k3, k3, 1)
self.texcoord.addData2f(0, 1)
#4.vertex:
k4=1
self.vertex.addData3f(array_sent[3].x,array_sent[3].y, array_sent[3].z)
self.normal.addData3f(self.myNormalize(Vec3(2*array_sent[3].x-1,2*array_sent[3].y-1,2*array_sent[3].z-1)))
self.color.addData4f(k4, k4, k4, 1)
self.texcoord.addData2f(0, 0)
#add to primitive:
one=numbr
two=numbr+1
three=numbr+2
four=numbr+3
prim_dat.addVertices(one, two, three)
prim_dat.addVertices(two, three, four)
w = run_me()
w.run()
Note that the first geom in the above case is just a flat plane with six different primitives that make six different faces.
The second geom is a trough made of six different primitives that make six different faces as well.
The problem arises with the second geom after the entire process is done. It’s data is rendered haphazardly, whereas querying the geom for the primitive and vertex-data before and after deletion shows that the data itself remains the same in terms of vertex-values, i.e. LVecBase3f data. However, if I only renumber the data from the first geom, no problem arises. Only when attempting to renumber data from both geoms does this issue arise. Both geoms reference data from the same vertex-table. Some screenshots:
Removing the primitives and vertices and renumbering data from only the first geom:[it visually works fine]
Removing the primitives and vertices and renumbering data from both geoms:[it visually does not work fine, geom 2’s data is rendered haphazardly]
What could be the issue? Did I miss something in my code? If any clarification is needed in terms of the question, please ask.
Thank you in advance.