예제 #1
0
//-------------------------------------------------------------
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;
}
예제 #2
0
//-------------------------------------------------------------
/// 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;
}
예제 #3
0
//-------------------------------------------------------------
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;
}
예제 #4
0
//-------------------------------------------------------------
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;
}
예제 #5
0
//-------------------------------------------------------------
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;
}