mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:26:43 +00:00 
			
		
		
		
	Added vertex transformation code
This commit is contained in:
		
							parent
							
								
									27ec79e33f
								
							
						
					
					
						commit
						70f9e63cd1
					
				
					 1 changed files with 101 additions and 9 deletions
				
			
		|  | @ -226,6 +226,49 @@ static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material | |||
|   if(!material.empty()) sub->setMaterialName(material); | ||||
| } | ||||
| 
 | ||||
| // Helper math functions. Reinventing linear algebra for the win!
 | ||||
| 
 | ||||
| // Computes B = AxB (matrix*matrix)
 | ||||
| static void matrixMul(const Matrix &A, Matrix &B) | ||||
| { | ||||
|   for(int i=0;i<3;i++) | ||||
|     { | ||||
|       float a = B.v[0].array[i]; | ||||
|       float b = B.v[1].array[i]; | ||||
|       float c = B.v[2].array[i]; | ||||
| 
 | ||||
|       B.v[0].array[i] = a*A[0].array[0] + b*A[0].array[1] + c*A[0].array[2]; | ||||
|       B.v[1].array[i] = a*A[1].array[0] + b*A[1].array[1] + c*A[1].array[2]; | ||||
|       B.v[2].array[i] = a*A[2].array[0] + b*A[2].array[1] + c*A[2].array[2]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Computes C = B + AxC*scale
 | ||||
| static void vectorMulAdd(const Matrix &A, const Vector &B, float *C, float scale) | ||||
| { | ||||
|   // Keep the original values
 | ||||
|   float a = C[0]; | ||||
|   float b = C[1]; | ||||
|   float c = C[2]; | ||||
| 
 | ||||
|   // Perform matrix multiplication, scaling and addition
 | ||||
|   for(int i=0;i<3;i++) | ||||
|     C[i] = B.array[i] + (a*A[i].array[0] + b*A[i].array[1] + c*A[i].array[2])*scale; | ||||
| } | ||||
| 
 | ||||
| // Computes B = AxB (matrix*vector)
 | ||||
| static void vectorMul(const Matrix &A, float *C) | ||||
| { | ||||
|   // Keep the original values
 | ||||
|   float a = C[0]; | ||||
|   float b = C[1]; | ||||
|   float c = C[2]; | ||||
| 
 | ||||
|   // Perform matrix multiplication, scaling and addition
 | ||||
|   for(int i=0;i<3;i++) | ||||
|     C[i] = a*A[i].array[0] + b*A[i].array[1] + c*A[i].array[2]; | ||||
| } | ||||
| 
 | ||||
| static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags) | ||||
| { | ||||
|   // Interpret flags
 | ||||
|  | @ -349,19 +392,46 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|   // TODO: Do in-place transformation of all the vertices and
 | ||||
|   // normals. This is pretty messy stuff, but we need it to make the
 | ||||
|   // sub-meshes appear in the correct place. We also need to do it
 | ||||
|   // anyway for collision meshes. Since all the pointers in the NIF
 | ||||
|   // structures are pointing to an internal temporary memory buffer,
 | ||||
|   // it's OK to overwrite them (even though the pointers technically
 | ||||
|   // are const.)
 | ||||
|   if(0) // TODO FIXME TEMP
 | ||||
|   { | ||||
|     /* Do in-place transformation of all the vertices and normals. This
 | ||||
|        is pretty messy stuff, but we need it to make the sub-meshes | ||||
|        appear in the correct place. Neither Ogre nor Bullet support | ||||
|        nested levels of sub-meshes with transformations applied to each | ||||
|        level. | ||||
|     */ | ||||
|     NiTriShapeData *data = shape->data.getPtr(); | ||||
|     int numVerts = data->vertices.length / 3; | ||||
| 
 | ||||
|     float *ptr = data->vertices.ptr; | ||||
| 
 | ||||
|     // Rotate, scale and translate all the vertices
 | ||||
|     const Matrix &rot = shape->trafo->rotation; | ||||
|     const Vector &pos = shape->trafo->position; | ||||
|     float scale = shape->trafo->scale; | ||||
|     for(int i=0; i<numVerts; i++) | ||||
|       { | ||||
|         vectorMulAdd(rot, pos, ptr, scale); | ||||
|         ptr += 3; | ||||
|       } | ||||
| 
 | ||||
|     // Remember to rotate all the vertex normals as well
 | ||||
|     if(data->normals.length) | ||||
|       { | ||||
|         ptr = data->normals.ptr; | ||||
|         for(int i=0; i<numVerts; i++) | ||||
|           { | ||||
|             vectorMul(rot, ptr); | ||||
|             ptr += 3; | ||||
|           } | ||||
|       } | ||||
|   } | ||||
| 
 | ||||
|   if(!hidden) | ||||
|     createOgreMesh(mesh, shape, material); | ||||
| } | ||||
| 
 | ||||
| static void handleNode(Mesh* mesh, Nif::Node *node, int flags) | ||||
| static void handleNode(Mesh* mesh, Nif::Node *node, int flags, const Transformation *trafo = NULL) | ||||
| { | ||||
|   // Accumulate the flags from all the child nodes. This works for all
 | ||||
|   // the flags we currently use, at least.
 | ||||
|  | @ -392,6 +462,28 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|   // Apply the parent transformation to this node. We overwrite the
 | ||||
|   // existing data with the final transformation.
 | ||||
|   if(0) // TODO FIXME TEMP
 | ||||
|   if(trafo) | ||||
|     { | ||||
|       // Get a non-const reference to the node's data, since we're
 | ||||
|       // overwriting it.
 | ||||
|       Transformation &final = *((Transformation*)node->trafo); | ||||
| 
 | ||||
|       // For both position and rotation we have that:
 | ||||
|       // final_vector = old_vector + old_rotation*new_vector*old_scale
 | ||||
|       vectorMulAdd(trafo->rotation, trafo->pos, final.pos.array, trafo->scale); | ||||
|       vectorMulAdd(trafo->rotation, trafo->velocity, final.velocity.array, trafo->scale); | ||||
| 
 | ||||
|       // Merge the rotations together
 | ||||
|       matrixMul(trafo->rotation, final.rotation); | ||||
| 
 | ||||
|       // Scalar values are so nice to deal with. Why can't everything
 | ||||
|       // just be scalars?
 | ||||
|       final.scale *= trafo->scale; | ||||
|     } | ||||
| 
 | ||||
|   // For NiNodes, loop through children
 | ||||
|   if(node->recType == RC_NiNode) | ||||
|     { | ||||
|  | @ -400,7 +492,7 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags) | |||
|       for(int i=0; i<n; i++) | ||||
|         { | ||||
|           if(list.has(i)) | ||||
|             handleNode(mesh, &list[i], flags); | ||||
|             handleNode(mesh, &list[i], flags, node->trafo); | ||||
|         } | ||||
|     } | ||||
|   else if(node->recType == RC_NiTriShape) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue