Code Search for Developers
 
 
  

MSModelFactory.cpp from Scorched 3D at Krugle


Show MSModelFactory.cpp syntax highlighted

////////////////////////////////////////////////////////////////////////////////
//    Scorched3D (c) 2000-2004
//
//    This file is part of Scorched3D.
//
//    Scorched3D is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    Scorched3D is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Scorched3D; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

#include <3dsparse/MSModelFactory.h>
#include <common/Defines.h>

MSModelFactory::MSModelFactory() : lineNo_(0)
{
}

MSModelFactory::~MSModelFactory()
{
}

Model *MSModelFactory::createModel(const char *fileName)
{
	Model *model = new Model();

	FILE *in = fopen(fileName, "r");
	if (!in)
	{
		dialogExit("MSModelFactory", formatString(
			"Failed to open MS model \"%s\"",
			fileName));
	}
	loadFile(in, fileName, model);
	model->setup();
	fclose(in);

	return model;
}

bool MSModelFactory::getNextLine(char *line, FILE *in)
{
	char * wincr; 
	while (fgets(line, 256, in) != 0)
	{
		lineNo_++;
		if (wincr=strchr(line,'\r')) 
		{ 
			*wincr='\n'; 
			*(wincr + 1) = '\0'; 
		} 

		if ((line[0] == '\\' && line[1] == '\\') ||
			(line[0] == '/' && line[1] == '/') ||
			(line[0] == '\0') || 
			(line[0] == '\n'))
		{
			// Skip this line
		}
		else return true;
	}

	return false;
}

void MSModelFactory::returnError(const char *fileName, const char *error)
{
	dialogExit("MSModelFactory", formatString("%s in file %i:%s", 
		error, lineNo_, fileName));
}

void MSModelFactory::loadFile(FILE *in, const char *fileName, Model *model)
{
	char filePath[256];
	snprintf(filePath, sizeof(filePath), "%s", fileName);

	char *sep;
	while (sep=strchr(filePath, '\\')) *sep = '/';
	sep = strrchr(filePath, '/');
	if (sep) *sep = '\0';

	char buffer[256];
	int frames = 0;
	if (!getNextLine(buffer, in)) returnError(fileName, "No frames");
	if (sscanf(buffer, "Frames: %i", &frames) != 1) 
		returnError(fileName, "Incorrect frames format");	
	model->setTotalFrames(frames);

	if (!getNextLine(buffer, in)) returnError(fileName, "No frame");
	if (sscanf(buffer, "Frame: %i", &frames) != 1) 
		returnError(fileName, "Incorrect frame format");	
	model->setStartFrame(frames);

	// Read number meshes
	int noMeshes = 0;
	if (!getNextLine(buffer, in)) returnError(fileName, "No meshes");
	if (sscanf(buffer, "Meshes: %i", &noMeshes) != 1) 
		returnError(fileName, "Incorrect meshes format");

	std::vector<int> meshMaterials;
	for (int i=0; i<noMeshes; i++)
	{
		// Read the mesh name, flags and material indices
		char meshName[256]; 
		int meshFlags, meshMatIndex;
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No mesh name");
		if (sscanf(buffer, "%s %i %i", meshName, &meshFlags, &meshMatIndex) != 3) 
			returnError(fileName, "Incorrect mesh name format");
		meshMaterials.push_back(meshMatIndex);
		
		// Create and add the new model
		Mesh *mesh = new Mesh(meshName);
		model->addMesh(mesh);

		// Read no vertices
		int noVertices = 0;
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No num vertices");
		if (sscanf(buffer, "%i", &noVertices) != 1) 
			returnError(fileName, "Incorrect num vertices format");

		int j;
		std::vector<Vector> tcoords;
		for (j=0; j<noVertices; j++)
		{
			// Read the current vertex
			int vertexFlags;
			Vector texCoord;
			Vertex vertex;
			if (!getNextLine(buffer, in)) 
				returnError(fileName, "No vertices");
			if (sscanf(buffer, "%i %f %f %f %f %f %i",
				&vertexFlags,
				&vertex.position[0], &vertex.position[2], &vertex.position[1], 
				&texCoord[0], &texCoord[1], &vertex.boneIndex) != 7)
				returnError(fileName, "Incorrect vertices format");
			texCoord[1]=1.0f-texCoord[1];

			tcoords.push_back(texCoord);
			mesh->insertVertex(vertex);
		}

		// Read no normals
		std::vector<Vector> normals;
		int noNormals = 0;
		if (!getNextLine(buffer, in)) 
				returnError(fileName, "No num normals");
		if (sscanf(buffer, "%i", &noNormals) != 1)
				returnError(fileName, "Incorrect num normals format");
		for (j=0; j<noNormals; j++)
		{
			// Read the current normal
			Vector normal;
			if (!getNextLine(buffer, in))
				returnError(fileName, "No normal");
			if (sscanf(buffer, "%f %f %f",
				&normal[0], &normal[2], &normal[1]) != 3)
				returnError(fileName, "Incorrect normal format");

			normals.push_back(normal.Normalize());
		}

		// Read no faces
		int noFaces = 0;
		if (!getNextLine(buffer, in)) 
				returnError(fileName, "No num faces");
		if (sscanf(buffer, "%i", &noFaces) != 1) 
				returnError(fileName, "Incorrect num faces format");
		for (j=0; j<noFaces; j++)
		{
			// Read the current face
			int faceFlags, sGroup;
			int nIndex1, nIndex2, nIndex3;
			Face face;
			if (!getNextLine(buffer, in))
				returnError(fileName, "No face");
			if (sscanf(buffer, "%i %i %i %i %i %i %i %i",
				&faceFlags,
				&face.v[0], &face.v[2], &face.v[1],
				&nIndex1, &nIndex3, &nIndex2,
				&sGroup) != 8)
				returnError(fileName, "Incorrect face format");

			mesh->insertFace(face);
			DIALOG_ASSERT (nIndex1 < (int) normals.size());
			mesh->setFaceNormal(normals[nIndex1], j, 0);
			DIALOG_ASSERT (nIndex2 < (int) normals.size());
			mesh->setFaceNormal(normals[nIndex2], j, 1);
			DIALOG_ASSERT (nIndex3 < (int) normals.size());
			mesh->setFaceNormal(normals[nIndex3], j, 2);

			DIALOG_ASSERT (face.v[0] < (int) tcoords.size());
			mesh->setFaceTCoord(tcoords[face.v[0]], j, 0);
			DIALOG_ASSERT (face.v[1] < (int) tcoords.size());
			mesh->setFaceTCoord(tcoords[face.v[1]], j, 1);
			DIALOG_ASSERT (face.v[2] < (int) tcoords.size());
			mesh->setFaceTCoord(tcoords[face.v[2]], j, 2);
		}
	}

	// Read number materials
	int noMaterials = 0;
	if (!getNextLine(buffer, in))
		returnError(fileName, "No num materials");
	if (sscanf(buffer, "Materials: %i", &noMaterials) != 1)
		returnError(fileName, "Incorrect num materials format");

	for (int m=0; m<noMaterials; m++)
	{
		// material: name
		char materialName[256];
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No material name");
		if (sscanf(buffer, "%s", materialName) != 1)
			returnError(fileName, "Incorrect material name format");

		// ambient
		Vector4 ambient;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No material ambient");
		if (sscanf(buffer, "%f %f %f %f", 
			&ambient[0], &ambient[1], &ambient[2], &ambient[3]) != 4) 
			returnError(fileName, "Incorrect material ambient format");

		// diffuse
		Vector4 diffuse;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No material diffuse");
		if (sscanf(buffer, "%f %f %f %f", 
			&diffuse[0], &diffuse[1], &diffuse[2], &diffuse[3]) != 4)
			returnError(fileName, "Incorrect material diffuse format");

		// specular
		Vector4 specular;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No material specular");
		if (sscanf(buffer, "%f %f %f %f", 
			&specular[0], &specular[1], &specular[2], &specular[3]) != 4)
			returnError(fileName, "Incorrect material specular format");

		// emissive
		Vector4 emissive;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No material emissive");
		if (sscanf(buffer, "%f %f %f %f", 
			&emissive[0], &emissive[1], &emissive[2], &emissive[3]) != 4)
			returnError(fileName, "Incorrect material emissive format");

		// shininess
		float shininess;
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No material shininess");
		if (sscanf(buffer, "%f", &shininess) != 1)
			returnError(fileName, "Incorrect material shininess format");

		// transparency
		float transparency;
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No material transparency");
		if (sscanf(buffer, "%f", &transparency) != 1)
			returnError(fileName, "Incorrect material transparency format");

		// color map
		char textureName[256];
		char fullTextureName[256];
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No material texture");
		if (sscanf(buffer, "%s", textureName) != 1)
			returnError(fileName, "No material texture format");
		textureName[strlen(textureName)-1] = '\0';
		snprintf(fullTextureName, 256, "%s/%s", filePath, &textureName[1]);
		while (sep=strchr(fullTextureName, '\\')) *sep = '/';

		// alphamap
		char textureNameAlpha[256];
		char fullTextureAlphaName[256];
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No material alpha texture");
		if (sscanf(buffer, "%s", textureNameAlpha) != 1)
			returnError(fileName, "No material alpha texture format");
		textureNameAlpha[strlen(textureNameAlpha)-1] = '\0';
		snprintf(fullTextureAlphaName, 256, "%s/%s", filePath, &textureNameAlpha[1]);
		while (sep=strchr(fullTextureAlphaName, '\\')) *sep = '/';

		// Assign this material to the appropriate meshes
		int modelIndex = 0;
		std::vector<Mesh *>::iterator mitor;
		for (mitor = model->getMeshes().begin();
			mitor != model->getMeshes().end();
			mitor++, modelIndex++)
		{
			if (meshMaterials[modelIndex] == m)
			{
				Mesh *mesh = *mitor;
				if (textureName[1]) // as the string starts with a "
				{
					mesh->setTextureName(fullTextureName);
					if (!s3d_fileExists(fullTextureName))
					{
						returnError(fileName, 
							formatString("Failed to find texture \"%s\"",
								fullTextureName));
					}
				}
				if (textureNameAlpha[1])
				{
					mesh->setATextureName(fullTextureAlphaName);
					if (!s3d_fileExists(fullTextureAlphaName))
					{
						returnError(fileName,
							formatString("Failed to find alpha texture \"%s\"",
								fullTextureAlphaName));
					}
				}
				mesh->getDiffuseColor() = diffuse;
				mesh->getAmbientColor() = ambient;
				mesh->getSpecularColor() = specular;
				mesh->getEmissiveColor() = emissive;
				mesh->getShininessColor() = shininess;
				mesh->getDiffuseNoTexColor() = diffuse;
				mesh->getAmbientNoTexColor() = ambient;
				mesh->getSpecularNoTexColor() = specular;
				mesh->getEmissiveNoTexColor() = emissive;
			}
		}
	}

	// Setup meshes with no materials
	int modelIndex = 0;
	std::vector<Mesh *>::iterator mitor;
	for (mitor = model->getMeshes().begin();
		mitor != model->getMeshes().end();
		mitor++, modelIndex++)
	{
		int materialIndex = meshMaterials[modelIndex];
		if (materialIndex == -1)
		{
			Mesh *mesh = *mitor;

			Vector4 ambientColor(0.3f, 0.3f, 0.3f, 1.0f);
			Vector4 diffuseColor(0.8f, 0.8f, 0.8f, 1.0f);
			mesh->getAmbientColor() = ambientColor;
			mesh->getDiffuseColor() = diffuseColor;
			mesh->getEmissiveColor() = Vector::nullVector;
			mesh->getSpecularColor() = Vector::nullVector;

			mesh->getAmbientNoTexColor() = ambientColor;
			mesh->getDiffuseNoTexColor() = diffuseColor;
			mesh->getEmissiveNoTexColor() = Vector::nullVector;
			mesh->getSpecularNoTexColor() = Vector::nullVector;

			mesh->getShininessColor() = 0.0f;
		}
	}


	////////////////
	// The bone's position and rotation are left in the milkshape native xyz coord
	// system and are not read in translated into the S3D system.
	// The translation is done during the bone calculation at runtime
	///////////////

	// Read number bones
	int noBones = 0;
	if (!getNextLine(buffer, in))
		returnError(fileName, "No num bones");
	if (sscanf(buffer, "Bones: %i", &noBones) != 1)
		returnError(fileName, "Incorrect num bones format");

	for (int b=0; b<noBones; b++)
	{
		// bone: name
		char boneName[256];
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No bone name");
		if (sscanf(buffer, "%s", boneName) != 1)
			returnError(fileName, "Incorrect bone name format");

		// bone parent
		char boneParentName[256];
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No bone parent name");
		if (sscanf(buffer, "%s", boneParentName) != 1)
			returnError(fileName, "Incorrect bone parent name format");

		// flags, position, rotation
		int boneFlags;
		Vector bonePos, boneRot;
		if (!getNextLine(buffer, in)) 
			returnError(fileName, "No bone pos/rot");
		if (sscanf(buffer, "%i %f %f %f %f %f %f",
			&boneFlags,
			&bonePos[0], &bonePos[1], &bonePos[2], 
			&boneRot[0], &boneRot[1], &boneRot[2]) != 7)
			returnError(fileName, "Incorrect bone pos/rot format");

		Bone *bone = new Bone(boneName);
		bone->setParentName(boneParentName);
		bone->setPosition(bonePos);
		bone->setRotation(boneRot);

		// position key
		int noPositionKeys = 0;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No bone position keys");
		if (sscanf(buffer, "%i", &noPositionKeys) != 1)
			returnError(fileName, "Incorrect bone position keys format");

		for (int p=0; p<noPositionKeys; p++)
		{
			float time;
			Vector position;
			if (!getNextLine(buffer, in)) 
				returnError(fileName, "No bone position key");
			if (sscanf(buffer, "%f %f %f %f",
				&time,
				&position[0], &position[1], &position[2]) != 4)
				returnError(fileName, "Incorrect bone position key");

			BonePositionKey *key = new BonePositionKey(time, position);
			bone->addPositionKey(key);
		}

		// rotation key
		int noRotationKeys = 0;
		if (!getNextLine(buffer, in))
			returnError(fileName, "No bone rotation keys");
		if (sscanf(buffer, "%i", &noRotationKeys) != 1)
			returnError(fileName, "Incorrect bone rotation keys format");

		for (int r=0; r<noRotationKeys; r++)
		{
			float time;
			Vector rotation;
			if (!getNextLine(buffer, in)) 
				returnError(fileName, "No bone position key");
			if (sscanf(buffer, "%f %f %f %f",
				&time,
				&rotation[0], &rotation[1], &rotation[2]) != 4)
				returnError(fileName, "Incorrect bone position key");

			BoneRotationKey *key = new BoneRotationKey(time, rotation);
			bone->addRotationKey(key);
		}

		// Add bone
		model->addBone(bone);
	}
}




See more files for this project here

Scorched 3D

Scorched3D is a 3D remake of the popular 2D artillery game Scorched Earth.\r\nScorched3D can be played against the computer, other players and remotely across the internet or LAN.

Project homepage: http://sourceforge.net/projects/scorched3d
Programming language(s): C,C++,XML
License: gpl2

  ASEModelFactory.cpp
  ASEModelFactory.h
  Bone.cpp
  Bone.h
  Face.cpp
  Face.h
  MSModelFactory.cpp
  MSModelFactory.h
  Mesh.cpp
  Mesh.h
  MeshLOD.cpp
  MeshLOD.h
  MeshLODTri.cpp
  MeshLODTri.h
  MeshLODVector.cpp
  MeshLODVector.h
  Model.cpp
  Model.h
  ModelDefn.cpp
  ModelDefn.h
  ModelMaths.cpp
  ModelMaths.h
  ModelStore.cpp
  ModelStore.h
  TreeModelFactory.cpp
  TreeModelFactory.h
  Vertex.cpp
  Vertex.h
  aseFile.lex.cpp
  aseFile.tab.cpp
  aseFile.tab.cpp.h