Esempio n. 1
0
Model* ModelLoader::realLoadAsset(const char* filename)
{
	std::ifstream in(filename, std::ios::in | std::ios::binary | std::ios::ate);
	if (!in.is_open())
	{
		std::cerr << "ModelLoader: File not found." << std::endl;
		return NULL;
	}

	size_t filesize = in.tellg();
	in.seekg(std::ios::beg);
	char* pPtr = NULL;
	char* buffer = new char[filesize];
	in.read(buffer, filesize);
	in.close();

	pPtr = buffer;
	ms3d_header_t* mshead = (ms3d_header_t*) pPtr;

	if (strncmp(mshead->id, "MS3D000000", 10) != 0)
	{
		std::cerr << "ModelLoader: Filetype unkown: " << mshead->id
				<< std::endl;
		delete buffer;
		return NULL;
	}

	if (mshead->version != 3 && mshead->version != 4)
	{
		std::cerr << "ModelLoader: MS3D wrong version: " << mshead->version
				<< std::endl;
		delete buffer;
		return NULL;
	}

	pPtr += sizeof(ms3d_header_t);
	std::vector<float>* l_interleaved;
	std::vector<unsigned short>* l_indices;

	Material* l_mat = NULL;
	Mesh* l_mesh = NULL;
	VertexBuffer* vb;
	IndexBuffer* ib;
	Model* l_mdl = new Model();
	float minx = 0, maxx = 0, miny = 0, maxy = 0, minz = 0, maxz = 0;
	int numIlEl = 9;
	bool animated = false;

	word numVertices = *((word*) pPtr);
	pPtr += sizeof(word);
	ms3d_vertex_t* vertices = (ms3d_vertex_t*) pPtr;
	pPtr += sizeof(ms3d_vertex_t) * numVertices;

	if ((short) vertices[0].boneId != (short) -1)
	{
		//enables bones & boneWeights
		numIlEl += 8;
		animated = true;
	}

	l_interleaved = new std::vector<float>(numVertices * numIlEl, 0.0f);
	for (int i = 0; i < numVertices; i++)
	{

		(*l_interleaved)[i * numIlEl + 0] = vertices[i].vertex[0]; // vertex - x
		(*l_interleaved)[i * numIlEl + 1] = vertices[i].vertex[1]; // vertex - y
		(*l_interleaved)[i * numIlEl + 2] = vertices[i].vertex[2]; // vertex - z
		(*l_interleaved)[i * numIlEl + 3] = 1.0f;

		if (animated)
			(*l_interleaved)[i * numIlEl + 9] = vertices[i].boneId;

		if (vertices[i].vertex[0] < minx)
			minx = vertices[i].vertex[0];
		if (vertices[i].vertex[0] > maxx)
			maxx = vertices[i].vertex[0];
		if (vertices[i].vertex[1] < miny)
			miny = vertices[i].vertex[1];
		if (vertices[i].vertex[1] > maxy)
			maxy = vertices[i].vertex[1];
		if (vertices[i].vertex[2] < minz)
			minz = vertices[i].vertex[2];
		if (vertices[i].vertex[2] > maxz)
			maxz = vertices[i].vertex[2];

	}

	word numFaces = *((word*) pPtr);
	pPtr += sizeof(word);
	ms3d_triangle_t* faces = (ms3d_triangle_t*) pPtr;
	pPtr += sizeof(ms3d_triangle_t) * numFaces;

	for (int i = 0; i < numFaces; i++)
	{
		for (int x = 0; x < 3; x++)
		{
			(*l_interleaved)[faces[i].vertexIndices[x] * numIlEl + 4] =
					faces[i].s[x];
			(*l_interleaved)[faces[i].vertexIndices[x] * numIlEl + 5] = 1.0f
					- faces[i].t[x];
			(*l_interleaved)[faces[i].vertexIndices[x] * numIlEl + 6] =
					faces[i].vertexNormals[x][0];
			(*l_interleaved)[faces[i].vertexIndices[x] * numIlEl + 7] =
					faces[i].vertexNormals[x][1];
			(*l_interleaved)[faces[i].vertexIndices[x] * numIlEl + 8] =
					faces[i].vertexNormals[x][2];
		}
	}

	vb = m_Ctx->createVertexBuffer();
	vb->init(l_interleaved->size());
	unsigned int stride = sizeof(float) * numIlEl;
	VertexBufferAttribute* pos = new VertexBufferAttribute(vb,
			Shader::VERTEX_POSITION, 4, stride, false, 0);
	VertexBufferAttribute* uv = new VertexBufferAttribute(vb,
			Shader::VERTEX_UV0, 2, stride, false, sizeof(float) * 4);
	VertexBufferAttribute* normal = new VertexBufferAttribute(vb,
			Shader::VERTEX_NORMAL, 3, stride, false, sizeof(float) * 6);
	VertexBufferAttribute* boneid = NULL, *boneweight = NULL;
	if (animated)
	{
		boneid = new VertexBufferAttribute(vb, Shader::VERTEX_BONE_ID, 4,
				stride, false, sizeof(float) * 9);
		boneweight = new VertexBufferAttribute(vb, Shader::VERTEX_BONE_WEIGHT,
				4, stride, false, sizeof(float) * 13);
	}

	word numGroups = *((word*) pPtr);
	pPtr += sizeof(word);
	ms3d_group_t* groups = (ms3d_group_t*) pPtr;
	word* index;

	for (int i = 0; i < numGroups; i++)
	{
		l_mesh = new Mesh();

		l_indices = new std::vector<unsigned short>(groups->numtriangles * 3,
				0);
		pPtr += sizeof(byte) + sizeof(char) * 32 + sizeof(word);
		for (unsigned int x = 0; x < groups->numtriangles; x++)
		{
			index = (word*) pPtr;
			for (int y = 0; y < 3; y++)
			{
				(*l_indices)[x * 3 + y] =
						(unsigned short) faces[*index].vertexIndices[y];
			}
			pPtr += sizeof(word);
		}

		ib = m_Ctx->createIndexBuffer();
		ib->init(l_indices->size());
		ib->uploadData(&(*l_indices)[0],l_indices->size());

		l_mesh->addVBAttribute(pos);
		l_mesh->addVBAttribute(uv);
		l_mesh->addVBAttribute(normal);
		if (animated)
		{
			l_mesh->addVBAttribute(boneid);
			l_mesh->addVBAttribute(boneweight);
		}
		l_mesh->setIndexBuffer(ib);
		l_mesh->setMaterialId((int) ((char) *pPtr));
		l_mdl->addMesh(l_mesh);

		pPtr += sizeof(char);
		groups = (ms3d_group_t*) pPtr;
	}

	unsigned int numMats = (unsigned int) *((word*) pPtr);
	pPtr += sizeof(word);
	ms3d_material_t* mats = (ms3d_material_t*) pPtr;
	pPtr += sizeof(ms3d_material_t) * numMats;

	for (unsigned int i = 0; i < numMats; i++)
	{
		l_mat = new Material();
		l_mat->setAmbientColor(
				glm::vec4(mats[i].ambient[0], mats[i].ambient[1],
						mats[i].ambient[2], mats[i].ambient[3]));
		l_mat->setDiffuseColor(
				glm::vec4(mats[i].diffuse[0], mats[i].diffuse[1],
						mats[i].diffuse[2], mats[i].diffuse[3]));
		l_mat->setSpecularColor(
				glm::vec4(mats[i].specular[0], mats[i].specular[1],
						mats[i].specular[2], mats[i].specular[3]));
		l_mat->setEmissiveColor(
				glm::vec4(mats[i].emissive[0], mats[i].emissive[1],
						mats[i].emissive[2], mats[i].emissive[3]));
		l_mat->setShininess(mats[i].shininess);
		Texture* t = m_TMgr->loadAsset(mats[i].texture);
		if (t != NULL)
		{
			l_mat->addDiffuseTexture(t);
		}

		l_mdl->setMaterial(i, l_mat);
	}
	l_mdl->setAABB(
			new AABoundingBox(glm::vec3(minx, miny, minz),
					glm::vec3(maxx, maxy, maxz)));

	if (animated)
	{
		float aniFps = *(float*) pPtr;
		pPtr += sizeof(float);

		float currTime = *(float*) pPtr;
		pPtr += sizeof(float);

		int totalFrames = *(int*) pPtr;
		pPtr += sizeof(int);

		unsigned int numJoints = (unsigned int) *((word*) pPtr);
		pPtr += sizeof(word);

		ms3d_joint_t* joint = NULL;
		ms3d_keyframe_rot_t* kf_rot = NULL;
		ms3d_keyframe_pos_t* kf_trans = NULL;
		std::vector<Bone*>* bones = new std::vector<Bone*>(numJoints);
		Bone* bn;
		char name[33];

		for (unsigned int i = 0; i < numJoints; i++)
		{
			joint = (ms3d_joint_t*) pPtr;
			pPtr += sizeof(byte) + sizeof(char) * 32 * 2 + sizeof(float) * 3 * 2
					+ sizeof(word) * 2;
			bn = new Bone();
			strncpy(name, joint->name, 32);
			name[32] = '\0';
			bn->setName(name);
			strncpy(name, joint->parentName, 32);
			bn->setParentName(name);

			bn->setReferenceTransformation(
					glm::vec3(joint->position[0], joint->position[1],
							joint->position[2]),
					glm::quat(
							glm::vec3(joint->rotation[0], joint->rotation[1],
									joint->rotation[2])));
			for (unsigned int x = 0; x < joint->numKeyFramesRot; x++)
			{
				kf_rot = (ms3d_keyframe_rot_t*) pPtr;
				pPtr += sizeof(ms3d_keyframe_rot_t);
				bn->addRotation(
						new Keyframe(kf_rot->time,
								glm::vec3(kf_rot->rotation[0],
										kf_rot->rotation[1],
										kf_rot->rotation[2])));
			}

			for (unsigned int x = 0; x < joint->numKeyFramesTrans; x++)
			{
				kf_trans = (ms3d_keyframe_pos_t*) pPtr;
				pPtr += sizeof(ms3d_keyframe_pos_t);
				bn->addPosition(
						new Keyframe(kf_trans->time,
								glm::vec3(kf_trans->position[0],
										kf_trans->position[1],
										kf_trans->position[2])));
			}

			(*bones)[i] = bn;
		}

		/********************************
		 *  Step Over Comments
		 *******************************/
		pPtr += sizeof(int); //subversion
		ms3d_comment_t* cmnt = NULL;
		unsigned int numCmnts = 0;
		for (int x = 0; x < 4; x++)
		{
			numCmnts = *(unsigned int*) pPtr;
			pPtr += sizeof(unsigned int);
			for (unsigned int i = 0; i < numCmnts; i++)
			{
				cmnt = (ms3d_comment_t*) pPtr;
				pPtr += sizeof(int) * 2;
				pPtr += sizeof(char) * cmnt->commentLength;
			}
		}
		/****************************
		 * End StepOver comments
		 ***************************/
		int subVersion = (int) *pPtr;
		pPtr += sizeof(int);
		if (subVersion == 1)
		{
			ms3d_vertex_ex_t1* vertex_extra = NULL;
			for (int i = 0; i < numVertices; i++)
			{
				vertex_extra = (ms3d_vertex_ex_t1*) pPtr;
				pPtr += sizeof(ms3d_vertex_ex_t1);
				(*l_interleaved)[i * numIlEl + 10] = vertex_extra->boneIds[0];
				(*l_interleaved)[i * numIlEl + 11] = vertex_extra->boneIds[1];
				(*l_interleaved)[i * numIlEl + 12] = vertex_extra->boneIds[2];
				(*l_interleaved)[i * numIlEl + 13] =
						((*l_interleaved)[i * numIlEl + 9] > -1) ?
								(float) vertex_extra->weights[0]
										/ (float) 255.0f :
								0.0f;
				(*l_interleaved)[i * numIlEl + 14] =
						((*l_interleaved)[i * numIlEl + 10] > -1) ?
								(float) vertex_extra->weights[1]
										/ (float) 255.0f :
								0.0f;
				(*l_interleaved)[i * numIlEl + 15] =
						((*l_interleaved)[i * numIlEl + 11] > -1) ?
								(float) vertex_extra->weights[2]
										/ (float) 255.0f :
								0.0f;
				(*l_interleaved)[i * numIlEl + 16] =
						((*l_interleaved)[i * numIlEl + 12] > -1) ?
								1.0f - (*l_interleaved)[i * numIlEl + 13]
										- (*l_interleaved)[i * numIlEl + 14]
										- (*l_interleaved)[i * numIlEl + 15] :
								0.0f;
			}
		}
		else if (subVersion == 2)
		{
			ms3d_vertex_ex_t2* vertex_extra = NULL;
			for (int i = 0; i < numVertices; i++)
			{
				vertex_extra = (ms3d_vertex_ex_t2*) pPtr;
				pPtr += sizeof(ms3d_vertex_ex_t2);
				(*l_interleaved)[i * numIlEl + 10] = vertex_extra->boneIds[0];
				(*l_interleaved)[i * numIlEl + 11] = vertex_extra->boneIds[1];
				(*l_interleaved)[i * numIlEl + 12] = vertex_extra->boneIds[2];
				// TODO: this boneweight is an ugly hack... review specification!
				(*l_interleaved)[i * numIlEl + 13] =
						((*l_interleaved)[i * numIlEl + 9] > -1) ? 1.0f : 0.0f; //(float)vertex_extra->weights[0]/(float)255.0f : 0.0f;
				(*l_interleaved)[i * numIlEl + 14] =
						((*l_interleaved)[i * numIlEl + 10] > -1) ?
								(float) vertex_extra->weights[1]
										/ (float) 255.0f :
								0.0f;
				(*l_interleaved)[i * numIlEl + 15] =
						((*l_interleaved)[i * numIlEl + 11] > -1) ?
								(float) vertex_extra->weights[2]
										/ (float) 255.0f :
								0.0f;
				(*l_interleaved)[i * numIlEl + 16] =
						((*l_interleaved)[i * numIlEl + 12] > -1) ?
								1.0f - (*l_interleaved)[i * numIlEl + 13]
										- (*l_interleaved)[i * numIlEl + 14]
										- (*l_interleaved)[i * numIlEl + 15] :
								0.0f;
			}
		}
		else
		{
			delete l_interleaved;
			delete l_mdl;
			delete buffer;
			return NULL;
		}

		Animation* ani = new Animation();
		ani->setFPS(aniFps);
		ani->setCurrTime(currTime);
		ani->setTotalFrames(totalFrames);
		ani->setBones(bones);
		ani->makeTree();
		l_mdl->setAnimation(ani);

		glm::vec4 vertex;
		for (int i = 0; i < numVertices; i++)
		{
			vertex = glm::vec4((*l_interleaved)[i * numIlEl + 0],
					(*l_interleaved)[i * numIlEl + 1],
					(*l_interleaved)[i * numIlEl + 2],
					(*l_interleaved)[i * numIlEl + 3]);
			vertex =
					(*bones)[(int) (*l_interleaved)[i * numIlEl + 9]]->getGlobalTransformationInverse()
							* vertex;
			(*l_interleaved)[i * numIlEl + 0] = vertex[0];
			(*l_interleaved)[i * numIlEl + 1] = vertex[1];
			(*l_interleaved)[i * numIlEl + 2] = vertex[2];
			(*l_interleaved)[i * numIlEl + 3] = vertex[3];
		}
	}
	vb->uploadData(&(*l_interleaved)[0],l_interleaved->size());

	delete l_interleaved;
	delete l_indices;
	delete buffer;

	return l_mdl;
}