void MFixedRenderer::drawDisplay(MSubMesh * subMesh, MDisplay * display, MVector3 * vertices, MVector3 * normals, MColor * colors) { M_PROFILE_SCOPE(MFixedRenderer::drawDisplay); MEngine * engine = MEngine::getInstance(); MRenderingContext * render = engine->getRenderingContext(); render->setColor4(MVector4(1, 1, 1, 1)); // get material MMaterial * material = display->getMaterial(); { float opacity = material->getOpacity(); if(opacity <= 0.0f) return; // data M_TYPES indicesType = subMesh->getIndicesType(); void * indices = subMesh->getIndices(); MVector2 * texCoords = subMesh->getTexCoords(); // begin / size unsigned int begin = display->getBegin(); unsigned int size = display->getSize(); // get properties M_PRIMITIVE_TYPES primitiveType = display->getPrimitiveType(); M_BLENDING_MODES blendMode = material->getBlendMode(); M_CULL_MODES cullMode = display->getCullMode(); MVector3 * diffuse = material->getDiffuse(); MVector3 * specular = material->getSpecular(); MVector3 * emit = material->getEmit(); float shininess = material->getShininess(); // get current fog color MVector3 currentFogColor; render->getFogColor(¤tFogColor); // set cull mode if(cullMode == M_CULL_NONE){ render->disableCullFace(); } else{ render->enableCullFace(); render->setCullMode(cullMode); } // texture passes unsigned int texturesPassNumber = MIN(8, material->getTexturesPassNumber()); // set blending mode render->setBlendingMode(blendMode); // alpha test if(blendMode != M_BLENDING_ALPHA && texturesPassNumber > 0) { MTexturePass * texturePass = material->getTexturePass(0); MTexture * texture = texturePass->getTexture(); if(texture) { if(texture->getTextureRef()->getComponents() > 3) render->setAlphaTest(0.5f); } } // set fog color depending on blending switch(blendMode) { case M_BLENDING_ADD: case M_BLENDING_LIGHT: render->setFogColor(MVector3(0, 0, 0)); break; case M_BLENDING_PRODUCT: render->setFogColor(MVector3(1, 1, 1)); break; } // fixed pipeline { // no FX render->bindFX(0); // Vertex render->enableVertexArray(); render->setVertexPointer(M_FLOAT, 3, vertices); // Normal if(normals) { render->enableNormalArray(); render->setNormalPointer(M_FLOAT, normals); } // Color if(colors) { render->disableLighting(); render->enableColorArray(); render->setColorPointer(M_UBYTE, 4, colors); } // Material render->setMaterialDiffuse(MVector4(diffuse->x, diffuse->y, diffuse->z, opacity)); render->setMaterialSpecular(MVector4(*specular)); render->setMaterialAmbient(MVector4()); render->setMaterialEmit(MVector4(*emit)); render->setMaterialShininess(shininess); // switch to texture matrix mode if(texturesPassNumber > 0) render->setMatrixMode(M_MATRIX_TEXTURE); else render->disableTexture(); // Textures int id = texturesPassNumber; for(unsigned int t=0; t<texturesPassNumber; t++) { MTexturePass * texturePass = material->getTexturePass(t); MTexture * texture = texturePass->getTexture(); if((! texture) || (! texCoords)) { render->bindTexture(0, t); render->disableTexture(); render->disableTexCoordArray(); continue; } // texCoords unsigned int offset = 0; if(subMesh->isMapChannelExist(texturePass->getMapChannel())) offset = subMesh->getMapChannelOffset(texturePass->getMapChannel()); // texture id unsigned int textureId = 0; MTextureRef * texRef = texture->getTextureRef(); if(texRef) textureId = texRef->getTextureId(); // bind texture render->bindTexture(textureId, t); render->enableTexture(); render->setTextureCombineMode(texturePass->getCombineMode()); render->setTextureUWrapMode(texture->getUWrapMode()); render->setTextureVWrapMode(texture->getVWrapMode()); // texture matrix render->loadIdentity(); render->translate(MVector2(0.5f, 0.5f)); render->scale(*texture->getTexScale()); render->rotate(MVector3(0, 0, -1), texture->getTexRotate()); render->translate(MVector2(-0.5f, -0.5f)); render->translate(*texture->getTexTranslate()); // texture coords render->enableTexCoordArray(); render->setTexCoordPointer(M_FLOAT, 2, texCoords + offset); } // switch back to modelview matrix mode if(texturesPassNumber > 0) render->setMatrixMode(M_MATRIX_MODELVIEW); // draw if(indices) { switch(indicesType) { case M_USHORT: render->drawElement(primitiveType, size, indicesType, (unsigned short*)indices + begin); break; case M_UINT: render->drawElement(primitiveType, size, indicesType, (unsigned int*)indices + begin); break; } } else{ render->drawArray(primitiveType, begin, size); } // disable arrays render->disableVertexArray(); if(normals) render->disableNormalArray(); if(colors) render->disableColorArray(); // restore textures for(int t=(int)(id-1); t>=0; t--) { render->bindTexture(0, t); render->disableTexture(); render->disableTexCoordArray(); render->setTextureCombineMode(M_TEX_COMBINE_MODULATE); render->setMatrixMode(M_MATRIX_TEXTURE); render->loadIdentity(); render->setMatrixMode(M_MATRIX_MODELVIEW); } } // restore fog and alpha test render->setFogColor(currentFogColor); if(blendMode != M_BLENDING_ALPHA) render->setAlphaTest(0.0f); // restore lighting if(colors) render->enableLighting(); } }
// Mesh bin export bool exportMeshBin(const char * filename, MMesh * mesh) { int version = 2; char rep[256]; bool state; // create file MFile * file = M_fopen(filename, "wb"); if(! file) { printf("Error : can't create file %s\n", filename); return false; } // get file directory getRepertory(rep, filename); // header M_fwrite(M_MESH_HEADER, sizeof(char), 8, file); // version M_fwrite(&version, sizeof(int), 1, file); // Animation { // anim refs MArmatureAnimRef * armatureAnimRef = mesh->getArmatureAnimRef(); MTexturesAnimRef * texturesAnimRef = mesh->getTexturesAnimRef(); MMaterialsAnimRef * materialsAnimRef = mesh->getMaterialsAnimRef(); // armature anim ref writeDataRef(file, armatureAnimRef, rep); // textures anim ref writeDataRef(file, texturesAnimRef, rep); // materials anim ref writeDataRef(file, materialsAnimRef, rep); // anims ranges unsigned int animsRangesNumber = mesh->getAnimsRangesNumber(); MAnimRange * animsRanges = mesh->getAnimsRanges(); M_fwrite(&animsRangesNumber, sizeof(int), 1, file); if(animsRangesNumber > 0) M_fwrite(animsRanges, sizeof(MAnimRange), animsRangesNumber, file); } // Textures { unsigned int t, texturesNumber = mesh->getTexturesNumber(); M_fwrite(&texturesNumber, sizeof(int), 1, file); for(t=0; t<texturesNumber; t++) { MTexture * texture = mesh->getTexture(t); MTextureRef * textureRef = texture->getTextureRef(); M_TEX_GEN_MODES genMode = texture->getGenMode(); M_WRAP_MODES UWrapMode = texture->getUWrapMode(); M_WRAP_MODES VWrapMode = texture->getVWrapMode(); MVector2 texTranslate = texture->getTexTranslate(); MVector2 texScale = texture->getTexScale(); float texRotate = texture->getTexRotate(); // texture ref writeDataRef(file, textureRef, rep); if(textureRef) { bool mipmap = textureRef->isMipmapEnabled(); M_fwrite(&mipmap, sizeof(bool), 1, file); } // data M_fwrite(&genMode, sizeof(M_TEX_GEN_MODES), 1, file); M_fwrite(&UWrapMode, sizeof(M_WRAP_MODES), 1, file); M_fwrite(&VWrapMode, sizeof(M_WRAP_MODES), 1, file); M_fwrite(&texTranslate, sizeof(MVector2), 1, file); M_fwrite(&texScale, sizeof(MVector2), 1, file); M_fwrite(&texRotate, sizeof(float), 1, file); } } // Materials { unsigned int m, materialsNumber = mesh->getMaterialsNumber(); M_fwrite(&materialsNumber, sizeof(int), 1, file); for(m=0; m<materialsNumber; m++) { MMaterial * material = mesh->getMaterial(m); int type = material->getType(); float opacity = material->getOpacity(); float shininess = material->getShininess(); float customValue = material->getCustomValue(); M_BLENDING_MODES blendMode = material->getBlendMode(); MVector3 emit = material->getEmit(); MVector3 diffuse = material->getDiffuse(); MVector3 specular = material->getSpecular(); MVector3 customColor = material->getCustomColor(); MFXRef * FXRef = material->getFXRef(); MFXRef * ZFXRef = material->getZFXRef(); // FX ref state = FXRef != NULL; M_fwrite(&state, sizeof(bool), 1, file); if(FXRef) { MShaderRef * vertShadRef = FXRef->getVertexShaderRef(); MShaderRef * pixShadRef = FXRef->getPixelShaderRef(); writeDataRef(file, vertShadRef, rep); writeDataRef(file, pixShadRef, rep); } // Z FX ref state = ZFXRef != NULL; M_fwrite(&state, sizeof(bool), 1, file); if(ZFXRef) { MShaderRef * vertShadRef = ZFXRef->getVertexShaderRef(); MShaderRef * pixShadRef = ZFXRef->getPixelShaderRef(); writeDataRef(file, vertShadRef, rep); writeDataRef(file, pixShadRef, rep); } // data M_fwrite(&type, sizeof(int), 1, file); M_fwrite(&opacity, sizeof(float), 1, file); M_fwrite(&shininess, sizeof(float), 1, file); M_fwrite(&customValue, sizeof(float), 1, file); M_fwrite(&blendMode, sizeof(M_BLENDING_MODES), 1, file); M_fwrite(&emit, sizeof(MVector3), 1, file); M_fwrite(&diffuse, sizeof(MVector3), 1, file); M_fwrite(&specular, sizeof(MVector3), 1, file); M_fwrite(&customColor, sizeof(MVector3), 1, file); // textures pass unsigned int t, texturesPassNumber = material->getTexturesPassNumber(); M_fwrite(&texturesPassNumber, sizeof(int), 1, file); for(t=0; t<texturesPassNumber; t++) { MTexturePass * texturePass = material->getTexturePass(t); MTexture * texture = texturePass->getTexture(); unsigned int mapChannel = texturePass->getMapChannel(); M_TEX_COMBINE_MODES combineMode = texturePass->getCombineMode(); // texture id int textureId = getTextureId(mesh, texture); M_fwrite(&textureId, sizeof(int), 1, file); // data M_fwrite(&mapChannel, sizeof(int), 1, file); M_fwrite(&combineMode, sizeof(M_TEX_COMBINE_MODES), 1, file); } } } // Bones { MArmature * armature = mesh->getArmature(); state = armature != NULL; M_fwrite(&state, sizeof(bool), 1, file); if(armature) { unsigned int b, bonesNumber = armature->getBonesNumber(); M_fwrite(&bonesNumber, sizeof(int), 1, file); for(b=0; b<bonesNumber; b++) { MOBone * bone = armature->getBone(b); MObject3d * parent = bone->getParent(); MVector3 position = bone->getPosition(); MVector3 scale = bone->getScale(); MQuaternion rotation = bone->getRotation(); // name writeString(file, bone->getName()); // parent id int parentId = -1; if(parent) { unsigned int id; if(armature->getBoneId(parent->getName(), &id)) parentId = (int)id; } M_fwrite(&parentId, sizeof(int), 1, file); // position / rotation / scale M_fwrite(&position, sizeof(MVector3), 1, file); M_fwrite(&rotation, sizeof(MQuaternion), 1, file); M_fwrite(&scale, sizeof(MVector3), 1, file); } } } // BoundingBox { MBox3d * box = mesh->getBoundingBox(); M_fwrite(box, sizeof(MBox3d), 1, file); } // SubMeshs { unsigned int s, subMeshsNumber = mesh->getSubMeshsNumber(); MSubMesh * subMeshs = mesh->getSubMeshs(); M_fwrite(&subMeshsNumber, sizeof(int), 1, file); for(s=0; s<subMeshsNumber; s++) { MSubMesh * subMesh = &(subMeshs[s]); unsigned int indicesSize = subMesh->getIndicesSize(); unsigned int verticesSize = subMesh->getVerticesSize(); unsigned int normalsSize = subMesh->getNormalsSize(); unsigned int tangentsSize = subMesh->getTangentsSize(); unsigned int texCoordsSize = subMesh->getTexCoordsSize(); unsigned int colorsSize = subMesh->getColorsSize(); M_TYPES indicesType = subMesh->getIndicesType(); void * indices = subMesh->getIndices(); MColor * colors = subMesh->getColors(); MVector3 * vertices = subMesh->getVertices(); MVector3 * normals = subMesh->getNormals(); MVector3 * tangents = subMesh->getTangents(); MVector2 * texCoords = subMesh->getTexCoords(); MBox3d * box = subMesh->getBoundingBox(); MSkinData * skin = subMesh->getSkinData(); map<unsigned int, unsigned int> * mapChannelOffsets = subMesh->getMapChannelOffsets(); // BoundingBox M_fwrite(box, sizeof(MBox3d), 1, file); // indices M_fwrite(&indicesSize, sizeof(int), 1, file); if(indicesSize > 0) { // indice type M_fwrite(&indicesType, sizeof(M_TYPES), 1, file); switch(indicesType) { case M_USHORT: M_fwrite(indices, sizeof(short), indicesSize, file); break; case M_UINT: M_fwrite(indices, sizeof(int), indicesSize, file); break; } } // vertices M_fwrite(&verticesSize, sizeof(int), 1, file); if(verticesSize > 0) M_fwrite(vertices, sizeof(MVector3), verticesSize, file); // normals M_fwrite(&normalsSize, sizeof(int), 1, file); if(normalsSize > 0) M_fwrite(normals, sizeof(MVector3), normalsSize, file); // tangents M_fwrite(&tangentsSize, sizeof(int), 1, file); if(tangentsSize > 0) M_fwrite(tangents, sizeof(MVector3), tangentsSize, file); // texCoords M_fwrite(&texCoordsSize, sizeof(int), 1, file); if(texCoordsSize > 0) M_fwrite(texCoords, sizeof(MVector2), texCoordsSize, file); // colors M_fwrite(&colorsSize, sizeof(int), 1, file); if(colorsSize > 0) M_fwrite(colors, sizeof(MColor), colorsSize, file); // mapChannels { unsigned int size = mapChannelOffsets->size(); M_fwrite(&size, sizeof(int), 1, file); map<unsigned int, unsigned int>::iterator mit (mapChannelOffsets->begin()), mend(mapChannelOffsets->end()); for(;mit!=mend;++mit) { M_fwrite(&mit->first, sizeof(int), 1, file); M_fwrite(&mit->second, sizeof(int), 1, file); } } // Skins state = skin != NULL; M_fwrite(&state, sizeof(bool), 1, file); if(skin) { // skin point unsigned int p, pointsNumber = skin->getPointsNumber(); M_fwrite(&pointsNumber, sizeof(int), 1, file); for(p=0; p<pointsNumber; p++) { MSkinPoint * skinPoint = skin->getPoint(p); unsigned int vertexId = skinPoint->getVertexId(); unsigned int bonesNumber = skinPoint->getBonesNumber(); unsigned short * bonesIds = skinPoint->getBonesIds(); float * bonesWeights = skinPoint->getBonesWeights(); // data M_fwrite(&vertexId, sizeof(int), 1, file); M_fwrite(&bonesNumber, sizeof(int), 1, file); if(bonesNumber > 0) { M_fwrite(bonesIds, sizeof(short), bonesNumber, file); M_fwrite(bonesWeights, sizeof(float), bonesNumber, file); } } } // Displays unsigned int d, displaysNumber = subMesh->getDisplaysNumber(); M_fwrite(&displaysNumber, sizeof(int), 1, file); for(d=0; d<displaysNumber; d++) { MDisplay * display = subMesh->getDisplay(d); M_PRIMITIVE_TYPES primitiveType = display->getPrimitiveType(); unsigned int begin = display->getBegin(); unsigned int size = display->getSize(); MMaterial * material = display->getMaterial(); M_CULL_MODES cullMode = display->getCullMode(); int materialId = getMaterialId(mesh, material); // data M_fwrite(&primitiveType, sizeof(M_PRIMITIVE_TYPES), 1, file); M_fwrite(&begin, sizeof(int), 1, file); M_fwrite(&size, sizeof(int), 1, file); M_fwrite(&materialId, sizeof(int), 1, file); M_fwrite(&cullMode, sizeof(M_CULL_MODES), 1, file); } } } M_fclose(file); return true; }
bool xmlMeshLoad(const char * filename, void * data) { MLOG_DEBUG("xmlMeshLoad " << filename?filename:"NULL"); MLevel * level = MEngine::getInstance()->getLevel(); // read document TiXmlDocument doc(filename); if(! doc.LoadFile()) { MLOG_WARNING("TiXmlDocument load failed : " << doc.ErrorDesc() << " line " << doc.ErrorRow()); return false; } TiXmlHandle hDoc(&doc); TiXmlElement * pRootNode; TiXmlHandle hRoot(0); // Maratis pRootNode = hDoc.FirstChildElement().Element(); if(! pRootNode) { MLOG_WARNING("Cannot find any root node"); return false; } if(strcmp(pRootNode->Value(), "Maratis") != 0) { MLOG_WARNING("Cannot find Maratis root node"); return false; } hRoot = TiXmlHandle(pRootNode); // Mesh TiXmlElement * pMeshNode = pRootNode->FirstChildElement("Mesh"); if(! pMeshNode) { MLOG_WARNING("Cannot find a Mesh node"); return false; } // create new mesh MMesh * mesh = (MMesh *)data; mesh->clear(); char path[256]; char meshRep[256]; char vertShadPath[256]; char fragShadPath[256]; // mesh rep getRepertory(meshRep, filename); // animation if(! loadAnim(pMeshNode, meshRep, mesh)) { // load external anim file (depracated) char animFilename[256]; strcpy(animFilename, filename); strcpy(animFilename + strlen(animFilename) - 4, "anim"); loadAnimFile(mesh, animFilename, meshRep); } // Textures TiXmlElement * texturesNode = pMeshNode->FirstChildElement("Textures"); if(texturesNode) { MLOG_DEBUG("entering Textures node"); unsigned int numTextures = 0; texturesNode->QueryUIntAttribute("num", &numTextures); mesh->allocTextures(numTextures); // Texture TiXmlElement * textureNode = texturesNode->FirstChildElement("Texture"); for(textureNode; textureNode; textureNode=textureNode->NextSiblingElement("Texture")) { const char * file = NULL; bool mipmap = true; // image TiXmlElement * imageNode = textureNode->FirstChildElement("image"); if(imageNode) { int value = 1; file = imageNode->Attribute("filename"); imageNode->QueryIntAttribute("mipmap", &value); mipmap = (value == 1); } if(! file) { mesh->addNewTexture(NULL); continue; } // load texture getGlobalFilename(path, meshRep, file); MTextureRef * texRef = level->loadTexture(path, mipmap); MTexture * texture = mesh->addNewTexture(texRef); // tile TiXmlElement * tileNode = textureNode->FirstChildElement("tile"); if(tileNode) { const char * uTile = tileNode->Attribute("u"); const char * vTile = tileNode->Attribute("v"); if(uTile){ if(strcmp(uTile, "clamp") == 0) texture->setUWrapMode(M_WRAP_CLAMP); else texture->setUWrapMode(M_WRAP_REPEAT); } if(vTile){ if(strcmp(vTile, "clamp") == 0) texture->setVWrapMode(M_WRAP_CLAMP); else texture->setVWrapMode(M_WRAP_REPEAT); } } // translate TiXmlElement * translateNode = textureNode->FirstChildElement("translate"); if(translateNode) { MVector2 translate = texture->getTexTranslate(); translateNode->QueryFloatAttribute("x", &translate.x); translateNode->QueryFloatAttribute("y", &translate.y); texture->setTexTranslate(translate); } // scale TiXmlElement * scaleNode = textureNode->FirstChildElement("scale"); if(scaleNode) { MVector2 scale = texture->getTexScale(); scaleNode->QueryFloatAttribute("x", &scale.x); scaleNode->QueryFloatAttribute("y", &scale.y); texture->setTexScale(scale); } // rotate TiXmlElement * rotateNode = textureNode->FirstChildElement("rotate"); if(rotateNode) { float angle = 0; rotateNode->QueryFloatAttribute("angle", &angle); texture->setTexRotate(angle); } } } // Materials TiXmlElement * materialsNode = pMeshNode->FirstChildElement("Materials"); if(materialsNode) { MLOG_DEBUG("entering Materials node"); unsigned int numMaterials = 0; materialsNode->QueryUIntAttribute("num", &numMaterials); mesh->allocMaterials(numMaterials); // Material TiXmlElement * materialNode = materialsNode->FirstChildElement("Material"); for(materialNode; materialNode; materialNode=materialNode->NextSiblingElement("Material")) { MMaterial * material = mesh->addNewMaterial(); int type = 0; materialNode->QueryIntAttribute("type", &type); material->setType(type); float opacity=1, shininess=0, customValue=0; MVector3 diffuseColor; MVector3 specularColor; MVector3 emitColor; MVector3 customColor; // blend int blendType = 0; TiXmlElement * blendNode = materialNode->FirstChildElement("blend"); if(blendNode) blendNode->QueryIntAttribute("type", &blendType); switch(blendType) { case 2: material->setBlendMode(M_BLENDING_ALPHA); break; case 3: material->setBlendMode(M_BLENDING_ADD); break; case 4: material->setBlendMode(M_BLENDING_PRODUCT); break; } // opacity TiXmlElement * opacityNode = materialNode->FirstChildElement("opacity"); if(opacityNode) opacityNode->QueryFloatAttribute("value", &opacity); // shininess TiXmlElement * shininessNode = materialNode->FirstChildElement("shininess"); if(shininessNode) shininessNode->QueryFloatAttribute("value", &shininess); // customValue TiXmlElement * customValueNode = materialNode->FirstChildElement("customValue"); if(customValueNode) customValueNode->QueryFloatAttribute("value", &customValue); material->setOpacity(opacity); material->setShininess(shininess); material->setCustomValue(customValue); // diffuseColor TiXmlElement * diffuseColorNode = materialNode->FirstChildElement("diffuseColor"); if(diffuseColorNode){ diffuseColorNode->QueryFloatAttribute("r", &diffuseColor.x); diffuseColorNode->QueryFloatAttribute("g", &diffuseColor.y); diffuseColorNode->QueryFloatAttribute("b", &diffuseColor.z); material->setDiffuse(diffuseColor); } // specularColor TiXmlElement * specularColorNode = materialNode->FirstChildElement("specularColor"); if(specularColorNode){ specularColorNode->QueryFloatAttribute("r", &specularColor.x); specularColorNode->QueryFloatAttribute("g", &specularColor.y); specularColorNode->QueryFloatAttribute("b", &specularColor.z); material->setSpecular(specularColor); } // emitColor TiXmlElement * emitColorNode = materialNode->FirstChildElement("emitColor"); if(emitColorNode){ emitColorNode->QueryFloatAttribute("r", &emitColor.x); emitColorNode->QueryFloatAttribute("g", &emitColor.y); emitColorNode->QueryFloatAttribute("b", &emitColor.z); material->setEmit(emitColor); } // customColor TiXmlElement * customColorNode = materialNode->FirstChildElement("customColor"); if(customColorNode){ customColorNode->QueryFloatAttribute("r", &customColor.x); customColorNode->QueryFloatAttribute("g", &customColor.y); customColorNode->QueryFloatAttribute("b", &customColor.z); material->setCustomColor(customColor); } // TexturesPass TiXmlElement * texturesPassNode = materialNode->FirstChildElement("TexturesPass"); if(texturesPassNode) { unsigned int numTexturesPass = 0; texturesPassNode->QueryUIntAttribute("num", &numTexturesPass); material->allocTexturesPass(numTexturesPass); // texturePass TiXmlElement * texturePassNode = texturesPassNode->FirstChildElement("texturePass"); for(texturePassNode; texturePassNode; texturePassNode=texturePassNode->NextSiblingElement("texturePass")) { int textureId = -1; unsigned int mapChannel = 0; const char * mode = texturePassNode->Attribute("mode"); texturePassNode->QueryIntAttribute("texture", &textureId); if(textureId < 0) { material->addTexturePass(NULL, M_TEX_COMBINE_MODULATE, 0); continue; } texturePassNode->QueryUIntAttribute("mapChannel", &mapChannel); // combine mode M_TEX_COMBINE_MODES texCombine = M_TEX_COMBINE_MODULATE; if(strcmp(mode, "modulate") == 0) texCombine = M_TEX_COMBINE_MODULATE; else if(strcmp(mode, "replace") == 0) texCombine = M_TEX_COMBINE_REPLACE; else if(strcmp(mode, "alpha") == 0) texCombine = M_TEX_COMBINE_ALPHA; else if(strcmp(mode, "dot") == 0) texCombine = M_TEX_COMBINE_DOT; else if(strcmp(mode, "add") == 0) texCombine = M_TEX_COMBINE_ADD; else if(strcmp(mode, "sub") == 0) texCombine = M_TEX_COMBINE_SUB; // add texture pass material->addTexturePass(mesh->getTexture(textureId), texCombine, mapChannel); } } // FX { // vertexShader const char * vertShadFile = NULL; TiXmlElement * vertexShaderNode = materialNode->FirstChildElement("vertexShader"); if(vertexShaderNode){ vertShadFile = vertexShaderNode->Attribute("file"); } // fragmentShader const char * fragShadFile = NULL; TiXmlElement * fragmentShaderNode = materialNode->FirstChildElement("fragmentShader"); if(fragmentShaderNode){ fragShadFile = fragmentShaderNode->Attribute("file"); } // create FX if(vertShadFile && fragShadFile) { getGlobalFilename(vertShadPath, meshRep, vertShadFile); getGlobalFilename(fragShadPath, meshRep, fragShadFile); MShaderRef * vertShad = level->loadShader(vertShadPath, M_SHADER_VERTEX); MShaderRef * pixShad = level->loadShader(fragShadPath, M_SHADER_PIXEL); if(vertShad && pixShad) { MFXRef * FXRef = level->createFX(vertShad, pixShad); material->setFXRef(FXRef); } } } // ZFX (optional optim) { // ZVertexShader const char * vertShadFile = NULL; TiXmlElement * vertexShaderNode = materialNode->FirstChildElement("ZVertexShader"); if(vertexShaderNode){ vertShadFile = vertexShaderNode->Attribute("file"); } // ZFragmentShader const char * fragShadFile = NULL; TiXmlElement * fragmentShaderNode = materialNode->FirstChildElement("ZFragmentShader"); if(fragmentShaderNode){ fragShadFile = fragmentShaderNode->Attribute("file"); } // create ZFX if(vertShadFile && fragShadFile) { getGlobalFilename(vertShadPath, meshRep, vertShadFile); getGlobalFilename(fragShadPath, meshRep, fragShadFile); MShaderRef * vertShad = level->loadShader(vertShadPath, M_SHADER_VERTEX); MShaderRef * pixShad = level->loadShader(fragShadPath, M_SHADER_PIXEL); if(vertShad && pixShad) { MFXRef * ZFXRef = level->createFX(vertShad, pixShad); material->setZFXRef(ZFXRef); } } } } } // Bones TiXmlElement * bonesNode = pMeshNode->FirstChildElement("Bones"); if(bonesNode) { MLOG_DEBUG("entering Bones node"); MArmature * armature = mesh->createArmature(); unsigned int b, numBones = 0; bonesNode->QueryUIntAttribute("num", &numBones); armature->allocBones(numBones); // add bones for(b=0; b<numBones; b++) armature->addNewBone(); b = 0; // Bone TiXmlElement * boneNode = bonesNode->FirstChildElement("Bone"); for(boneNode; boneNode; boneNode=boneNode->NextSiblingElement("Bone")) { if(b >= armature->getBonesNumber()) break; MOBone * bone = armature->getBone(b); const char * name = boneNode->Attribute("name"); if(name) bone->setName(name); // parent TiXmlElement * parentNode = boneNode->FirstChildElement("parent"); if(parentNode){ unsigned int boneId = 0; parentNode->QueryUIntAttribute("id", &boneId); bone->linkTo(armature->getBone(boneId)); } // position TiXmlElement * positionNode = boneNode->FirstChildElement("position"); if(positionNode){ MVector3 position; positionNode->QueryFloatAttribute("x", &position.x); positionNode->QueryFloatAttribute("y", &position.y); positionNode->QueryFloatAttribute("z", &position.z); bone->setPosition(position); } // rotation TiXmlElement * rotationNode = boneNode->FirstChildElement("rotation"); if(rotationNode){ MVector3 euler; rotationNode->QueryFloatAttribute("x", &euler.x); rotationNode->QueryFloatAttribute("y", &euler.y); rotationNode->QueryFloatAttribute("z", &euler.z); bone->setEulerRotation(euler); } // scale TiXmlElement * scaleNode = boneNode->FirstChildElement("scale"); if(scaleNode){ MVector3 scale; scaleNode->QueryFloatAttribute("x", &scale.x); scaleNode->QueryFloatAttribute("y", &scale.y); scaleNode->QueryFloatAttribute("z", &scale.z); bone->setScale(scale); } b++; } // construct bones inverse pose matrix armature->constructBonesInversePoseMatrix(); } // SubMeshs TiXmlElement * subMeshsNode = pMeshNode->FirstChildElement("SubMeshs"); if(! subMeshsNode) return true; unsigned int numSubMeshs = 0; subMeshsNode->QueryUIntAttribute("num", &numSubMeshs); if(numSubMeshs == 0) return true; // alloc subMeshs MSubMesh * subMeshs = mesh->allocSubMeshs(numSubMeshs); // BoundingBox TiXmlElement * boundingBoxNode = pMeshNode->FirstChildElement("BoundingBox"); if(boundingBoxNode) { MVector3 * min = &mesh->getBoundingBox()->min; MVector3 * max = &mesh->getBoundingBox()->max; boundingBoxNode->QueryFloatAttribute("minx", &min->x); boundingBoxNode->QueryFloatAttribute("miny", &min->y); boundingBoxNode->QueryFloatAttribute("minz", &min->z); boundingBoxNode->QueryFloatAttribute("maxx", &max->x); boundingBoxNode->QueryFloatAttribute("maxy", &max->y); boundingBoxNode->QueryFloatAttribute("maxz", &max->z); } // SubMesh TiXmlElement * SubMeshNode = subMeshsNode->FirstChildElement("SubMesh"); for(SubMeshNode; SubMeshNode; SubMeshNode=SubMeshNode->NextSiblingElement("SubMesh")) { MSubMesh * subMesh = subMeshs; // BoundingBox boundingBoxNode = SubMeshNode->FirstChildElement("BoundingBox"); if(boundingBoxNode) { MVector3 * min = &subMesh->getBoundingBox()->min; MVector3 * max = &subMesh->getBoundingBox()->max; boundingBoxNode->QueryFloatAttribute("minx", &min->x); boundingBoxNode->QueryFloatAttribute("miny", &min->y); boundingBoxNode->QueryFloatAttribute("minz", &min->z); boundingBoxNode->QueryFloatAttribute("maxx", &max->x); boundingBoxNode->QueryFloatAttribute("maxy", &max->y); boundingBoxNode->QueryFloatAttribute("maxz", &max->z); } // Vertices TiXmlElement * verticesNode = SubMeshNode->FirstChildElement("Vertices"); if(verticesNode) { unsigned int numVertices = 0; verticesNode->QueryUIntAttribute("num", &numVertices); MVector3 * vertices = subMesh->allocVertices(numVertices); // vertex TiXmlElement * vertexNode = verticesNode->FirstChildElement("vertex"); for(vertexNode; vertexNode; vertexNode=vertexNode->NextSiblingElement("vertex")) { vertexNode->QueryFloatAttribute("x", &vertices->x); vertexNode->QueryFloatAttribute("y", &vertices->y); vertexNode->QueryFloatAttribute("z", &vertices->z); vertices++; } } // Normals TiXmlElement * normalsNode = SubMeshNode->FirstChildElement("Normals"); if(normalsNode) { unsigned int numNormals = 0; normalsNode->QueryUIntAttribute("num", &numNormals); MVector3 * normals = subMesh->allocNormals(numNormals); // normal TiXmlElement * normalNode = normalsNode->FirstChildElement("normal"); for(normalNode; normalNode; normalNode=normalNode->NextSiblingElement("normal")) { normalNode->QueryFloatAttribute("x", &normals->x); normalNode->QueryFloatAttribute("y", &normals->y); normalNode->QueryFloatAttribute("z", &normals->z); normals->normalize(); normals++; } } // Tangents TiXmlElement * tangentsNode = SubMeshNode->FirstChildElement("Tangents"); if(tangentsNode) { unsigned int numTangents = 0; tangentsNode->QueryUIntAttribute("num", &numTangents); MVector3 * tangents = subMesh->allocTangents(numTangents); // tangent TiXmlElement * tangentNode = tangentsNode->FirstChildElement("tangent"); for(tangentNode; tangentNode; tangentNode=tangentNode->NextSiblingElement("tangent")) { tangentNode->QueryFloatAttribute("x", &tangents->x); tangentNode->QueryFloatAttribute("y", &tangents->y); tangentNode->QueryFloatAttribute("z", &tangents->z); tangents->normalize(); tangents++; } } // TexCoords TiXmlElement * texCoordsNode = SubMeshNode->FirstChildElement("TexCoords"); if(texCoordsNode) { // num unsigned int numTexCoords = 0; texCoordsNode->QueryUIntAttribute("num", &numTexCoords); MVector2 * texCoords = subMesh->allocTexCoords(numTexCoords); // mapChannels unsigned int numVertices = subMesh->getVerticesSize(); const char * mapChannelsData = texCoordsNode->Attribute("mapChannels"); // read channels if(mapChannelsData) { char str[256]; strcpy(str, mapChannelsData); char * pch; unsigned int offset = 0; pch = strtok(str, " "); while(pch != NULL) { unsigned int channel = 0; sscanf(pch, "%d", &channel); subMesh->setMapChannelOffset(channel, offset); pch = strtok(NULL, " "); offset += numVertices; } } // create default channels else if((numVertices > 0) && (numTexCoords > numVertices)) { unsigned int numChannels = numTexCoords / numVertices; for(unsigned int c=0; c<numChannels; c++) subMesh->setMapChannelOffset(c, numVertices*c); } // texCoord TiXmlElement * texCoordNode = texCoordsNode->FirstChildElement("texCoord"); for(texCoordNode; texCoordNode; texCoordNode=texCoordNode->NextSiblingElement("texCoord")) { texCoordNode->QueryFloatAttribute("x", &texCoords->x); texCoordNode->QueryFloatAttribute("y", &texCoords->y); texCoords++; } } // Colors TiXmlElement * colorsNode = SubMeshNode->FirstChildElement("Colors"); if(colorsNode) { unsigned int numColors = 0; colorsNode->QueryUIntAttribute("num", &numColors); MColor * colors = subMesh->allocColors(numColors); // color TiXmlElement * colorNode = colorsNode->FirstChildElement("color"); for(colorNode; colorNode; colorNode=colorNode->NextSiblingElement("color")) { float x = 1, y = 1, z = 1, w = 1; colorNode->QueryFloatAttribute("x", &x); colorNode->QueryFloatAttribute("y", &y); colorNode->QueryFloatAttribute("z", &z); colorNode->QueryFloatAttribute("w", &w); colors->r = (unsigned char)x*255; colors->g = (unsigned char)y*255; colors->b = (unsigned char)z*255; colors->a = (unsigned char)w*255;; colors++; } } // Indices TiXmlElement * indicesNode = SubMeshNode->FirstChildElement("Indices"); if(indicesNode) { M_TYPES indicesType; unsigned int vSize = subMesh->getVerticesSize(); if(vSize < 65536){ indicesType = M_USHORT; } else{ indicesType = M_UINT; } unsigned int numIndices = 0; indicesNode->QueryUIntAttribute("num", &numIndices); subMesh->allocIndices(numIndices, indicesType); // indices TiXmlElement * indexNode = indicesNode->FirstChildElement("index"); switch(indicesType) { case M_USHORT: { unsigned short * indices = (unsigned short *)subMesh->getIndices(); for(indexNode; indexNode; indexNode=indexNode->NextSiblingElement("index")) { unsigned int id; indexNode->QueryUIntAttribute("value", &id); *indices = (unsigned short)id; indices++; } } break; case M_UINT: { unsigned int * indices = (unsigned int *)subMesh->getIndices(); for(indexNode; indexNode; indexNode=indexNode->NextSiblingElement("index")) { indexNode->QueryUIntAttribute("value", indices); indices++; } } break; } } // Skins TiXmlElement * skinsNode = SubMeshNode->FirstChildElement("Skins"); if(skinsNode) { MSkinData * skinData = subMesh->createSkinData(); unsigned int numSkins = 0; skinsNode->QueryUIntAttribute("num", &numSkins); MSkinPoint * skinPoints = skinData->allocPoints(numSkins); // skin TiXmlElement * skinNode = skinsNode->FirstChildElement("skin"); for(skinNode; skinNode; skinNode=skinNode->NextSiblingElement("skin")) { unsigned int vertexId = 0; unsigned int numBones = 0; skinNode->QueryUIntAttribute("vertex", &vertexId); skinNode->QueryUIntAttribute("numBones", &numBones); if(numBones > 0) { skinPoints->setVertexId(vertexId); skinPoints->allocateBonesLinks(numBones); unsigned short * bonesIds = skinPoints->getBonesIds(); float * bonesWeights = skinPoints->getBonesWeights(); TiXmlElement * boneNode = skinNode->FirstChildElement("bone"); for(boneNode; boneNode; boneNode=boneNode->NextSiblingElement("bone")) { unsigned int id; boneNode->QueryUIntAttribute("id", &id); boneNode->QueryFloatAttribute("weight", bonesWeights); *bonesIds = id; bonesIds++; bonesWeights++; } } skinPoints++; } } // Displays TiXmlElement * displaysNode = SubMeshNode->FirstChildElement("Displays"); if(displaysNode) { unsigned int numDisplays = 0; displaysNode->QueryUIntAttribute("num", &numDisplays); subMesh->allocDisplays(numDisplays); // display TiXmlElement * displayNode = displaysNode->FirstChildElement("display"); for(displayNode; displayNode; displayNode=displayNode->NextSiblingElement("display")) { unsigned int begin, size, material, cullFace = 0; displayNode->QueryUIntAttribute("begin", &begin); displayNode->QueryUIntAttribute("size", &size); displayNode->QueryUIntAttribute("material", &material); displayNode->QueryUIntAttribute("cullFace", &cullFace); // create display MDisplay * display = subMesh->addNewDisplay(M_PRIMITIVE_TRIANGLES, begin, size); // set material if(material < mesh->getMaterialsNumber()) display->setMaterial(mesh->getMaterial(material)); // set cull mode M_CULL_MODES cullMode = M_CULL_BACK; if(cullFace == 1) cullMode = M_CULL_FRONT; else if(cullFace == 2) cullMode = M_CULL_NONE; display->setCullMode(cullMode); } } // generate tangents if needed if(! subMesh->getTangents()) generateTangents(subMesh); subMeshs++; } MLOG_DEBUG("xmlMeshLoad success: "<<numSubMeshs<<" submeshs found"); return true; }