If I understand this and Linus is right, then calculating the vectors seams simple:
I got as far as this:
def generateTBN(np):
geomNode = np.find('**/+GeomNode').node()
geom = geomNode.modifyGeom(0)
vdata = geom.modifyVertexData()
tangent = GeomVertexWriter(vdata, 'tangent')
binormal = GeomVertexWriter(vdata, 'binormal')
normal = GeomVertexReader(vdata, 'normal')
while not normal.isAtEnd():
N = normal.getData3f()
tangent.setData3f(float3(N.x, N.z, -N.y))
binormal.setData3f(float3(N.z, N.y, -N.x))
Assertion failed: has_column() at line 508 of c:\buildslave\release_sdk_win32\bu
ild\panda3d\panda\src\gobj\geomVertexWriter.I
Traceback (most recent call last):
File "geo.py", line 47, in <module>
w = World()
File "geo.py", line 33, in __init__
generateTBN(self.terrain.getRoot())
File "geo.py", line 16, in generateTBN
tangent.setData3f(Vec3(N.x, N.z, -N.y))
AssertionError: has_column() at line 508 of c:\buildslave\release_sdk_win32\buil
d\panda3d\panda\src\gobj\geomVertexWriter.I
Reading the manual on Modifying existing geometry data, GeomVertexFormat and Defining your own GeomVertexFormat only gave me a headache.
Help, tips, solutions or working code would be welcome.
Unfortunately this is where the problem lies I think. It seems that you haven’t setup the extra columns in your GeomVertexFormat needed to handle the binormal and tangent information. I’ve done this quite a bit with procedurally generated geometry but I don’t how it would translate to imported models; the basic idea is:
# Build array for new format.
array = GeomVertexArrayFormat()
array.addColumn(InternalName.make('vertex'), 3, Geom.NTFloat32, Geom.CPoint)
array.addColumn(InternalName.make('color'), 4, Geom.NTFloat32, Geom.Ccolor)
array.addColumn(InternalName.make('texcoord'), 2, Geom.NTFloat32, Geom.CTexcoord)
array.addColumn(InternalName.make('normal'), 3, Geom.NTFloat32, Geom.CVector)
array.addColumn(InternalName.make('binormal'), 3, Geom.NTFloat32, Geom.CVector)
array.addColumn(InternalName.make('tangent'), 3, Geom.NTFloat32, Geom.CVector)
# Create and register format.
format = GeomVertexFormat()
format.addArray(array)
format = GeomVertexFormat.registerFormat(format)
# Create vdata and vertex writers.
vdata = GeomVertexData('name', format, Geom.UHStatic)
vertex = GeomVertexWriter(vdata, 'vertex')
color = GeomVertexWriter(vdata, 'color')
normal = GeomVertexWriter(vdata, 'normal')
texcoord = GeomVertexWriter(vdata, 'texcoord')
binormal = GeomVertexWriter(vdata, 'binormal')
tangent = GeomVertexWriter(vdata, 'tangent')
# Write to verts.
for vert in verts:
vertex.addData3f(vert.x, vert.y, vert.z)
...
tangent.addData3f(tx, ty, tz)
Like I said I don’t know how this works with imported models but this might be adaptable to your case. I’m not sure whether redefining the vformat means that you would have to rewrite all your columns (like the above code) or whether you could get away with just writing to the binormal and tangent columns.
Thanks.
But how can I set the format if I’m using vdata = geom.modifyVertexData() ? modifyVertexData() won’t take any parameters.
Do I have to make a totally new mesh on the fly that is just a copy of the mesh generated by GeoMipTerrain, add my tangent/binormal to it and finally throw away the original mesh? Seams a bit wasteful and way to complicated … and I don’t even know how to copy the polygons (primitives).
I had a look at the C++ code under GeoMipTerrain (geoMipTerrain.cxx) and it doesn’t look as adding tangent/binormals to it would be a big problem for someone that actually knows C++