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; }