//------------------------------------------------------------- VCNResID VCNMeshLoader::LoadMeshElementTextureCoordXML( XMLNodePtr elementNode, VCNCacheType coordType ) { XMLNodePtr node = NULL; // Fetch the node we need from the element node switch( coordType ) { case VT_DIFFUSE_TEX_COORDS: elementNode->selectSingleNode( (VCNTChar*)kNodeDiffuseTexCoords, &node ); break; case VT_NORMAL_TEX_COORDS: elementNode->selectSingleNode( (VCNTChar*)kNodeNormalTexCoords, &node ); break; default: VCN_ASSERT( false && "Trying to load unrecognized coord type!" ); } // If we didn't find it, we don't have it if( node == NULL ) return kInvalidResID; // Get the expected size of the array VCNUInt size = 0; GetAttributeUInt( node, kAttrVertexTexCoordsSize, size ); // If we don't have any, leave. if( size == 0 ) return kInvalidResID; // Create an array to contain all of this (2 floats per position) VCNUInt stride = size * kTexCoordFloats; VCNFloat* buffer = new VCNFloat[ stride ]; // Create some tools... VCNFloat* ptrFloat = buffer; VCNInt safety = 0; // Read the XML and fill the array! XMLNodeListPtr textureCoords = 0; node->selectNodes( (VCNTChar*)kNodeVertexTexCoord, &textureCoords ); VCNLong textureCoordsLength = 0; textureCoords->get_length( &textureCoordsLength ); VCN_ASSERT( textureCoordsLength == size && "FILE IS CORRUPTED!" ); for( VCNLong i=0; i<textureCoordsLength; i++ ) { // Get the first one XMLNodePtr textureCoordNode = 0; textureCoords->get_item( i, &textureCoordNode ); // Read the U GetAttributeFloat( textureCoordNode, kAttrVertexTexCoordU, *ptrFloat ); ptrFloat++; // Read the V GetAttributeFloat( textureCoordNode, kAttrVertexTexCoordV, *ptrFloat ); ptrFloat++; // Verify the safety to make sure we're reading in the right order GetAttributeInt( textureCoordNode, kAttrVertexTexCoordID, safety ); VCN_ASSERT( safety==i && "VERTEX AREN'T READ IN ORDER!" ); } // Now give the information to the cache manager // (he'll take care of making this data API specific) VCNResID cacheID = VCNRenderCore::GetInstance()->CreateCache( coordType, buffer, stride*sizeof(VCNFloat) ); // Clear the buffer delete [] buffer; // Return the cache ID return cacheID; }
//------------------------------------------------------------- /// A lighting array is composed of normals and colors //------------------------------------------------------------- VCNResID VCNMeshLoader::LoadMeshElementLightingXML( XMLNodePtr elementNode ) { // Fetch the normals from the element node XMLNodePtr normals = 0; elementNode->selectSingleNode( (VCNTChar*)kNodeVertexNormals, &normals ); bool hasNormals = (normals != NULL); // Fetch the colors from the element node XMLNodePtr colors = 0; elementNode->selectSingleNode( (VCNTChar*)kNodeVertexColors, &colors ); bool hasColors = (colors != NULL); // Get the expected size of the normals VCNUInt normalSize = 0; if( hasNormals ) { GetAttributeUInt( normals, kAttrVertexNormalsSize, normalSize ); if( normalSize == 0 ) hasNormals = false; } // Get the expected size of the colors VCNUInt colorSize = 0; if( hasColors ) { GetAttributeUInt( colors, kAttrVertexColorsSize, colorSize ); if( colorSize == 0 ) hasColors = false; } // If we have neither, then no lighting information at all if( !hasColors && !hasNormals ) return kInvalidResID; // If we have both, they MUST be of same size! if( hasColors && hasNormals && (normalSize != colorSize) ) { VCN_ASSERT_FAIL( "LIGHTING REJECTED!" ); return kInvalidResID; } // Now just retain one of the sizes VCNLong size = (VCNLong)(hasNormals?normalSize:colorSize); // Create an array to contain all of this (6 floats per vertex) VCNUInt stride = size * (kNormalFloats+kColorFloats); VCNFloat* buffer = new VCNFloat[ stride ]; // Create some tools... VCNFloat* ptrFloat = buffer; VCNInt safety = 0; // Pick out the nodes of every normal (if we have them) XMLNodeListPtr normalElements; if( hasNormals ) { normalElements = 0; normals->selectNodes( (VCNTChar*)kNodeVertexNormal, &normalElements ); VCNLong normalElementsLength = 0; normalElements->get_length( &normalElementsLength ); VCN_ASSERT( normalElementsLength == size && "FILE IS CORRUPTED!" ); } // Pick out the nodes of every color (if we have them) XMLNodeListPtr colorsElements; if( hasColors ) { colorsElements = 0; colors->selectNodes( (VCNTChar*)kNodeVertexColor, &colorsElements ); VCNLong colorElementsLength = 0; normalElements->get_length( &colorElementsLength ); VCN_ASSERT( colorElementsLength == size && "FILE IS CORRUPTED!" ); } // Now read it in! for( VCNLong i=0; i<size; i++ ) { // Normals if( hasNormals ) { // Get the element's node XMLNodePtr normalNode = 0; normalElements->get_item( i, &normalNode ); // Read the X GetAttributeFloat( normalNode, kAttrVertexNormalX, *ptrFloat ); ptrFloat++; // Read the Y GetAttributeFloat( normalNode, kAttrVertexNormalY, *ptrFloat ); ptrFloat++; // Read the Z GetAttributeFloat( normalNode, kAttrVertexNormalZ, *ptrFloat ); ptrFloat++; // Verify the safety to make sure we're reading in the right order GetAttributeInt( normalNode, kAttrVertexNormalID, safety ); VCN_ASSERT( safety==i && "VERTEX AREN'T READ IN ORDER!" ); } else { // Put three zeros instead *ptrFloat = 0.0f; ptrFloat++; *ptrFloat = 0.0f; ptrFloat++; *ptrFloat = 0.0f; ptrFloat++; } // Then colors if( hasColors ) { // Get the element's node XMLNodePtr colorNode = 0; colorsElements->get_item( i, &colorNode ); // Read the X GetAttributeFloat( colorNode, kAttrVertexColorR, *ptrFloat ); ptrFloat++; // Read the Y GetAttributeFloat( colorNode, kAttrVertexColorG, *ptrFloat ); ptrFloat++; // Read the Z GetAttributeFloat( colorNode, kAttrVertexColorB, *ptrFloat ); ptrFloat++; // Verify the safety to make sure we're reading in the right order GetAttributeInt( colorNode, kAttrVertexColorID, safety ); VCN_ASSERT( safety==i && "VERTEX AREN'T READ IN ORDER!" ); } else { // Put three ones instead (white) *ptrFloat = 1.0f; ptrFloat++; *ptrFloat = 1.0f; ptrFloat++; *ptrFloat = 1.0f; ptrFloat++; } } // Now give the information to the cache manager // (he'll take care of making this data API specific) VCNResID cacheID = VCNRenderCore::GetInstance()->CreateCache( VT_LIGHTING, buffer, stride*sizeof(VCNFloat) ); // Clear the buffer delete [] buffer; // Return the cache ID return cacheID; }
//------------------------------------------------------------- VCNResID VCNMeshLoader::LoadMeshElementFaceXML( XMLNodePtr elementNode ) { // Fetch the node we need from the element node XMLNodePtr node = 0; elementNode->selectSingleNode( (VCNTChar*)kNodeFaces, &node ); // It might very well be that we aren't using indexes if( node == NULL ) return kInvalidResID; // Get the expected size of the array VCNUInt size = 0; GetAttributeUInt( node, kAttrFacesSize, size ); // If we don't have any, leave. if( size == 0 ) return kInvalidResID; // Create an array to contain all of this (3 indexes per face) VCNUInt stride = kFaceUShorts * kCacheStrides[VT_INDEX]; VCNUInt numBytes = size * stride; VCNByte* buffer = new VCNByte[numBytes]; // Create some tools... VCNUShort* ptrFaces = (VCNUShort*)buffer; VCNInt safety = 0; // Read the XML and fill the array! XMLNodeListPtr faces = 0; node->selectNodes( (VCNTChar*)kNodeFace, &faces ); VCNLong facesLength = 0; faces->get_length( &facesLength ); VCN_ASSERT( facesLength == size && "FILE IS CORRUPTED!" ); for( VCNLong i=0; i<facesLength; i++ ) { // Get the element's node XMLNodePtr faceNode = 0; faces->get_item( i, &faceNode ); // Read the X GetAttributeUShort( faceNode, kAttrFace1, *ptrFaces ); ptrFaces++; // Read the Y GetAttributeUShort( faceNode, kAttrFace2, *ptrFaces ); ptrFaces++; // Read the Z GetAttributeUShort( faceNode, kAttrFace3, *ptrFaces ); ptrFaces++; // Verify the safety to make sure we're reading in the right order GetAttributeInt( faceNode, kAttrVertexPositionID, safety ); VCN_ASSERT( safety==i && "VERTEX AREN'T READ IN ORDER!" ); } // Now give the information to the cache manager // (he'll take care of making this data API specific) VCNResID cacheID = VCNRenderCore::GetInstance()->CreateCache( VT_INDEX, buffer, numBytes ); // Clear the buffer delete [] buffer; // Return the cache ID return cacheID; }
//------------------------------------------------------------- VCNResID VCNMeshLoader::LoadMeshElementPositionXML( XMLNodePtr elementNode, VCNSphere* bounding, VCNAabb* aabb /*= NULL*/ ) { // Fetch the node we need from the element node XMLNodePtr node = 0; elementNode->selectSingleNode( (VCNTChar*)kNodeVertexPositions, &node ); VCN_ASSERT( node != NULL && "No positions in mesh!" ); // Get the expected size of the array VCNUInt size = 0; GetAttributeUInt( node, kAttrVertexPositionsSize, size ); // If we don't have any, leave. if( size == 0 ) return kInvalidResID; // Create an array to contain all of this (3 floats per position) VCNUInt stride = size * kPositionFloats; VCNFloat* buffer = new VCNFloat[ stride ]; // Create some tools... VCNFloat* ptrFloat = buffer; VCNInt safety = 0; // Keep track of the min and max VCNFloat minX, maxX; VCNFloat minY, maxY; VCNFloat minZ, maxZ; minX = minY = minZ = kMaxFloat; maxX = maxY = maxZ = kMinFloat; // Read the XML and fill the array! XMLNodeListPtr positions = 0; node->selectNodes( (VCNTChar*)kNodeVertexPosition, &positions ); VCN_ASSERT( positions != 0 && "FILE IS CORRUPTED!" ); VCNLong positionsLength = 0; positions->get_length( &positionsLength ); VCN_ASSERT( positionsLength == size && "FILE IS CORRUPTED!" ); for( VCNLong i=0; i<positionsLength; i++ ) { // Get the element's node XMLNodePtr positionNode = 0; positions->get_item( i, &positionNode ); // Read the X GetAttributeFloat( positionNode, kAttrVertexPositionX, *ptrFloat ); if( *ptrFloat < minX ) minX = *ptrFloat; if( *ptrFloat > maxX ) maxX = *ptrFloat; ptrFloat++; // Read the Y GetAttributeFloat( positionNode, kAttrVertexPositionY, *ptrFloat ); if( *ptrFloat < minY ) minY = *ptrFloat; if( *ptrFloat > maxY ) maxY = *ptrFloat; ptrFloat++; // Read the Z GetAttributeFloat( positionNode, kAttrVertexPositionZ, *ptrFloat ); if( *ptrFloat < minZ ) minZ = *ptrFloat; if( *ptrFloat > maxZ ) maxZ = *ptrFloat; ptrFloat++; // Verify the safety to make sure we're reading in the right order GetAttributeInt( positionNode, kAttrVertexPositionID, safety ); VCN_ASSERT( safety==i && "VERTEX AREN'T READ IN ORDER!" ); } // Now give the information to the cache manager // (he'll take care of making this data API specific) VCNResID cacheID = VCNRenderCore::GetInstance()->CreateCache( VT_POSITION, buffer, stride*sizeof(VCNFloat) ); // Clear the buffer delete [] buffer; Vector3 minVect ( minX, minY, minZ ); Vector3 maxVect ( maxX, maxY, maxZ ); Vector3 diagonal = (maxVect - minVect) / 2.0f; // If he wants us to fill the AABB, we'll do it for him if( bounding ) { VCNSphere tmpSphere( diagonal.Length(), minVect + diagonal ); *bounding = tmpSphere; } if (aabb) { VCNAabb tempAabb(minVect, maxVect); *aabb = tempAabb; } // Return the cache ID return cacheID; }
//------------------------------------------------------------- VCNAnim* VCNAnimLoader::LoadAnimXML( const VCNString& filename ) { // Create the new mesh to be filled! VCNAnim* newAnim = NULL; // Open the XML document XMLElementPtr pRootElem = LoadDocumentRoot( filename ); VCN_ASSERT_MSG( pRootElem != NULL, "Could not load XML Animation!" ); // Go through all the MeshElement nodes XMLNodeListPtr elementNodes; pRootElem->selectNodes( (VCNTChar*)kAttrAnimNode, &elementNodes ); VCNLong animNodeCount; elementNodes->get_length( &animNodeCount ); for( VCNLong i=0; i<animNodeCount; i++ ) { // Create the new mesh to be filled! newAnim = new VCNAnim(); // Get the element's node XMLNodePtr elementNode; elementNodes->get_item( i, &elementNode ); // Load the base properties LoadResourceBaseProperties( elementNode, newAnim ); // Go through all the joints that compose this anims XMLNodeListPtr jointNodes; elementNode->selectNodes( (VCNTChar*)kNodeAnimJoint, &jointNodes ); VCNLong jointNodeCount; jointNodes->get_length( &jointNodeCount ); for( VCNLong i=0; i<jointNodeCount; i++ ) { // Get the mesh's node XMLNodePtr jointNode; jointNodes->get_item( i, &jointNode ); // Load the joint VCNAnimJoint* animJoint = LoadJointXML( jointNode ); // The name of the joint will be the name of the anim + the target joint animJoint->SetName( newAnim->GetName() + VCNTXT("_") + animJoint->GetTargetName() ); // Add it to the resource manager VCNResID jointID = VCNResourceCore::GetInstance()->AddResource( animJoint->GetName(), animJoint ); // Add it to the animation newAnim->AddJoint( jointID ); } // Make sure we aren't loading it twice VCN_ASSERT( !VCNResourceCore::GetInstance()->GetResource<VCNAnim>( newAnim->GetName() ) ); // Add it VCNResourceCore::GetInstance()->AddResource( newAnim->GetName(), newAnim ); } // Free up the doc memory ReleaseDocument(); return newAnim; }