Material::Material() { ambient(1,1,1,1); diffuse(1,1,1,1); emissive(1,1,1,1); specular(1,1,1,1); m_shininess = 100; m_texture = -1; m_pTextureFilename = 0; }
void SetOpenGlDefaultMaterial() { glm::vec4 ambient( 0.2, 0.2, 0.2, 1.0 ); glm::vec4 specular( 0.0, 0.0, 0.0, 1.0 ); glm::vec4 emissive( 0.0, 0.0, 0.0, 1.0 ); glm::vec4 diffuse( 0.0, 0.0, 0.0, 1.0 ); GLint shininess_value = 0; glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value ); glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.x ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x ); glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.x ); glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.x ); }
VType *CopyMesh(INDICES &indices, LptaSkin::ID &skinId, const aiScene *scene, MANAGERS &managers) { VType *vertices = new VType(); vector<LptaSkin::ID> skinIds; for (unsigned int matIdx = 0; matIdx < scene->mNumMaterials; ++matIdx) { aiMaterial *mat = scene->mMaterials[matIdx]; aiColor4D diffuse(0.0f, 0.0f, 0.0f, 0.0f); aiColor4D ambient(0.0f, 0.0f, 0.0f, 0.0f); aiColor4D specular(0.0f, 0.0f, 0.0f, 0.0f); aiColor4D emissive(0.0f, 0.0f, 0.0f, 0.0f); float specularPower = 0.0f; mat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); mat->Get(AI_MATKEY_COLOR_AMBIENT, ambient); mat->Get(AI_MATKEY_COLOR_SPECULAR, specular); mat->Get(AI_MATKEY_COLOR_EMISSIVE, emissive); mat->Get(AI_MATKEY_SHININESS, specularPower); aiGetMaterialColor(mat, AI_MATKEY_COLOR_EMISSIVE, &emissive); LptaMaterial::ID materialId = managers.material.AddOrRetrieveMaterial( LptaColor(diffuse.r, diffuse.g, diffuse.b, diffuse.a), LptaColor(ambient.r, ambient.g, ambient.b, diffuse.a), LptaColor(specular.r, specular.g, specular.b, specular.a), LptaColor(emissive.r, emissive.g, emissive.b, emissive.a), specularPower ); LptaSkin::TEXTURE_IDS textureIds; // only diffuse texture is supported for now for (unsigned int texIdx = 0; texIdx < mat->GetTextureCount(aiTextureType_DIFFUSE) && texIdx < LptaSkin::MAX_TEXTURES; ++texIdx) { aiString filepath; mat->GetTexture(aiTextureType_DIFFUSE, texIdx, &filepath); LptaTexture::ID textureId = managers.texture.AddOrRetrieveTexture(filepath.C_Str()); textureIds.push_back(textureId); } LptaSkin::ID skinId = managers.skin.AddSkin(materialId, textureIds, false); skinIds.push_back(skinId); } for (unsigned int meshIdx = 0; meshIdx < scene->mNumMeshes; ++meshIdx) { const aiMesh *mesh = scene->mMeshes[meshIdx]; CopyAlgorithm::Copy(*vertices, indices, *mesh, vertices->GetNumVertices()); skinId = skinIds.at(mesh->mMaterialIndex); } return vertices; }
void SurfacePropertiesCS::parsePhong( TiXmlElement* techniqueRoot ) { // create a material float power = 2; if ( techniqueRoot->FirstChildElement( "shininess" ) ) { const char* valStr = techniqueRoot->FirstChildElement( "shininess" )->FirstChildElement( "float" )->GetText(); sscanf_s( valStr, "%f", &power ); } Color ambient( 0.7f, 0.7f, 0.7f, 1 ); if ( techniqueRoot->FirstChildElement( "ambient" ) ) { const char* valStr = techniqueRoot->FirstChildElement( "ambient" )->FirstChildElement( "color" )->GetText(); sscanf_s( valStr, "%f %f %f %f", &ambient.r, &ambient.g, &ambient.b, &ambient.a ); } Color diffuse( 0.7f, 0.7f, 0.7f, 1 ); if ( techniqueRoot->FirstChildElement( "diffuse" ) ) { const char* valStr = techniqueRoot->FirstChildElement( "diffuse" )->FirstChildElement( "color" )->GetText(); sscanf_s( valStr, "%f %f %f %f", &diffuse.r, &diffuse.g, &diffuse.b, &diffuse.a ); } Color specular( 0.9f, 0.9f, 0.9f, 1 ); if ( techniqueRoot->FirstChildElement( "specular" ) ) { const char* valStr = techniqueRoot->FirstChildElement( "specular" )->FirstChildElement( "color" )->GetText(); sscanf_s( valStr, "%f %f %f %f", &specular.r, &specular.g, &specular.b, &specular.a ); } Color emissive( 0, 0, 0 ); if ( techniqueRoot->FirstChildElement( "emission" ) ) { const char* valStr = techniqueRoot->FirstChildElement( "emission" )->FirstChildElement( "color" )->GetText(); sscanf_s( valStr, "%f %f %f %f", &emissive.r, &emissive.g, &emissive.b, &emissive.a ); } m_surfaceProperties = new SurfaceProperties( ambient, diffuse, specular, emissive, power ); }
bool Model::LoadAssimp(const char *filename) { Assimp::Importer importer; // remove unused data importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_COLORS | aiComponent_LIGHTS | aiComponent_CAMERAS); // max triangles and vertices per mesh, splits above this threshold importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, INT_MAX); importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, 0xfffe); // avoid the primitive restart index // remove points and lines importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE); const aiScene *scene = importer.ReadFile(filename, aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_RemoveComponent | aiProcess_GenSmoothNormals | aiProcess_SplitLargeMeshes | aiProcess_ValidateDataStructure | //aiProcess_ImproveCacheLocality | // handled by optimizePostTransform() aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | aiProcess_FindInvalidData | aiProcess_GenUVCoords | aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph); if (scene == nullptr) return false; if (scene->HasTextures()) { // embedded textures... } if (scene->HasAnimations()) { // todo } m_Header.materialCount = scene->mNumMaterials; m_pMaterial = new Material [m_Header.materialCount]; memset(m_pMaterial, 0, sizeof(Material) * m_Header.materialCount); for (unsigned int materialIndex = 0; materialIndex < scene->mNumMaterials; materialIndex++) { const aiMaterial *srcMat = scene->mMaterials[materialIndex]; Material *dstMat = m_pMaterial + materialIndex; aiColor3D diffuse(1.0f, 1.0f, 1.0f); aiColor3D specular(1.0f, 1.0f, 1.0f); aiColor3D ambient(1.0f, 1.0f, 1.0f); aiColor3D emissive(0.0f, 0.0f, 0.0f); aiColor3D transparent(1.0f, 1.0f, 1.0f); float opacity = 1.0f; float shininess = 0.0f; float specularStrength = 1.0f; aiString texDiffusePath; aiString texSpecularPath; aiString texEmissivePath; aiString texNormalPath; aiString texLightmapPath; aiString texReflectionPath; srcMat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); srcMat->Get(AI_MATKEY_COLOR_SPECULAR, specular); srcMat->Get(AI_MATKEY_COLOR_AMBIENT, ambient); srcMat->Get(AI_MATKEY_COLOR_EMISSIVE, emissive); srcMat->Get(AI_MATKEY_COLOR_TRANSPARENT, transparent); srcMat->Get(AI_MATKEY_OPACITY, opacity); srcMat->Get(AI_MATKEY_SHININESS, shininess); srcMat->Get(AI_MATKEY_SHININESS_STRENGTH, specularStrength); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), texDiffusePath); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, 0), texSpecularPath); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_EMISSIVE, 0), texEmissivePath); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0), texNormalPath); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0), texLightmapPath); srcMat->Get(AI_MATKEY_TEXTURE(aiTextureType_REFLECTION, 0), texReflectionPath); dstMat->diffuse = Vector3(diffuse.r, diffuse.g, diffuse.b); dstMat->specular = Vector3(specular.r, specular.g, specular.b); dstMat->ambient = Vector3(ambient.r, ambient.g, ambient.b); dstMat->emissive = Vector3(emissive.r, emissive.g, emissive.b); dstMat->transparent = Vector3(transparent.r, transparent.g, transparent.b); dstMat->opacity = opacity; dstMat->shininess = shininess; dstMat->specularStrength = specularStrength; char *pRem = nullptr; strncpy_s(dstMat->texDiffusePath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texDiffusePath, texDiffusePath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texDiffusePath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension strncpy_s(dstMat->texSpecularPath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texSpecularPath, texSpecularPath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texSpecularPath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension strncpy_s(dstMat->texEmissivePath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texEmissivePath, texEmissivePath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texEmissivePath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension strncpy_s(dstMat->texNormalPath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texNormalPath, texNormalPath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texNormalPath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension strncpy_s(dstMat->texLightmapPath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texLightmapPath, texLightmapPath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texLightmapPath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension strncpy_s(dstMat->texReflectionPath, "models/", Material::maxTexPath - 1); strncat_s(dstMat->texReflectionPath, texReflectionPath.C_Str(), Material::maxTexPath - 1); pRem = strrchr(dstMat->texReflectionPath, '.'); while (pRem != nullptr && *pRem != 0) *(pRem++) = 0; // remove extension aiString matName; srcMat->Get(AI_MATKEY_NAME, matName); strncpy_s(dstMat->name, matName.C_Str(), Material::maxMaterialName - 1); } m_Header.meshCount = scene->mNumMeshes; m_pMesh = new Mesh [m_Header.meshCount]; memset(m_pMesh, 0, sizeof(Mesh) * m_Header.meshCount); // first pass, count everything for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; meshIndex++) { const aiMesh *srcMesh = scene->mMeshes[meshIndex]; Mesh *dstMesh = m_pMesh + meshIndex; assert(srcMesh->mPrimitiveTypes == aiPrimitiveType_TRIANGLE); dstMesh->materialIndex = srcMesh->mMaterialIndex; // just store everything as float. Can quantize in Model::optimize() dstMesh->attribsEnabled |= attrib_mask_position; dstMesh->attrib[attrib_position].offset = dstMesh->vertexStride; dstMesh->attrib[attrib_position].normalized = 0; dstMesh->attrib[attrib_position].components = 3; dstMesh->attrib[attrib_position].format = attrib_format_float; dstMesh->vertexStride += sizeof(float) * 3; dstMesh->attribsEnabled |= attrib_mask_texcoord0; dstMesh->attrib[attrib_texcoord0].offset = dstMesh->vertexStride; dstMesh->attrib[attrib_texcoord0].normalized = 0; dstMesh->attrib[attrib_texcoord0].components = 2; dstMesh->attrib[attrib_texcoord0].format = attrib_format_float; dstMesh->vertexStride += sizeof(float) * 2; dstMesh->attribsEnabled |= attrib_mask_normal; dstMesh->attrib[attrib_normal].offset = dstMesh->vertexStride; dstMesh->attrib[attrib_normal].normalized = 0; dstMesh->attrib[attrib_normal].components = 3; dstMesh->attrib[attrib_normal].format = attrib_format_float; dstMesh->vertexStride += sizeof(float) * 3; dstMesh->attribsEnabled |= attrib_mask_tangent; dstMesh->attrib[attrib_tangent].offset = dstMesh->vertexStride; dstMesh->attrib[attrib_tangent].normalized = 0; dstMesh->attrib[attrib_tangent].components = 3; dstMesh->attrib[attrib_tangent].format = attrib_format_float; dstMesh->vertexStride += sizeof(float) * 3; dstMesh->attribsEnabled |= attrib_mask_bitangent; dstMesh->attrib[attrib_bitangent].offset = dstMesh->vertexStride; dstMesh->attrib[attrib_bitangent].normalized = 0; dstMesh->attrib[attrib_bitangent].components = 3; dstMesh->attrib[attrib_bitangent].format = attrib_format_float; dstMesh->vertexStride += sizeof(float) * 3; // depth-only dstMesh->attribsEnabledDepth |= attrib_mask_position; dstMesh->attribDepth[attrib_position].offset = dstMesh->vertexStrideDepth; dstMesh->attribDepth[attrib_position].normalized = 0; dstMesh->attribDepth[attrib_position].components = 3; dstMesh->attribDepth[attrib_position].format = attrib_format_float; dstMesh->vertexStrideDepth += sizeof(float) * 3; // color rendering dstMesh->vertexDataByteOffset = m_Header.vertexDataByteSize; dstMesh->vertexCount = srcMesh->mNumVertices; dstMesh->indexDataByteOffset = m_Header.indexDataByteSize; dstMesh->indexCount = srcMesh->mNumFaces * 3; m_Header.vertexDataByteSize += dstMesh->vertexStride * dstMesh->vertexCount; m_Header.indexDataByteSize += sizeof(uint16_t) * dstMesh->indexCount; // depth-only rendering dstMesh->vertexDataByteOffsetDepth = m_Header.vertexDataByteSizeDepth; dstMesh->vertexCountDepth = srcMesh->mNumVertices; m_Header.vertexDataByteSizeDepth += dstMesh->vertexStrideDepth * dstMesh->vertexCountDepth; } // allocate storage m_pVertexData = new unsigned char [m_Header.vertexDataByteSize]; m_pIndexData = new unsigned char [m_Header.indexDataByteSize]; m_pVertexDataDepth = new unsigned char [m_Header.vertexDataByteSizeDepth]; m_pIndexDataDepth = new unsigned char [m_Header.indexDataByteSize]; // second pass, fill in vertex and index data for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; meshIndex++) { const aiMesh *srcMesh = scene->mMeshes[meshIndex]; Mesh *dstMesh = m_pMesh + meshIndex; float *dstPos = (float*)(m_pVertexData + dstMesh->vertexDataByteOffset + dstMesh->attrib[attrib_position].offset); float *dstTexcoord0 = (float*)(m_pVertexData + dstMesh->vertexDataByteOffset + dstMesh->attrib[attrib_texcoord0].offset); float *dstNormal = (float*)(m_pVertexData + dstMesh->vertexDataByteOffset + dstMesh->attrib[attrib_normal].offset); float *dstTangent = (float*)(m_pVertexData + dstMesh->vertexDataByteOffset + dstMesh->attrib[attrib_tangent].offset); float *dstBitangent = (float*)(m_pVertexData + dstMesh->vertexDataByteOffset + dstMesh->attrib[attrib_bitangent].offset); float *dstPosDepth = (float*)(m_pVertexDataDepth + dstMesh->vertexDataByteOffsetDepth + dstMesh->attribDepth[attrib_position].offset); for (unsigned int v = 0; v < dstMesh->vertexCount; v++) { if (srcMesh->mVertices) { dstPos[0] = srcMesh->mVertices[v].x; dstPos[1] = srcMesh->mVertices[v].y; dstPos[2] = srcMesh->mVertices[v].z; dstPosDepth[0] = srcMesh->mVertices[v].x; dstPosDepth[1] = srcMesh->mVertices[v].y; dstPosDepth[2] = srcMesh->mVertices[v].z; } else { // no position? That's kind of bad. assert(0); } dstPos = (float*)((unsigned char*)dstPos + dstMesh->vertexStride); dstPosDepth = (float*)((unsigned char*)dstPosDepth + dstMesh->vertexStrideDepth); if (srcMesh->mTextureCoords[0]) { dstTexcoord0[0] = srcMesh->mTextureCoords[0][v].x; dstTexcoord0[1] = srcMesh->mTextureCoords[0][v].y; } else { dstTexcoord0[0] = 0.0f; dstTexcoord0[1] = 0.0f; } dstTexcoord0 = (float*)((unsigned char*)dstTexcoord0 + dstMesh->vertexStride); if (srcMesh->mNormals) { dstNormal[0] = srcMesh->mNormals[v].x; dstNormal[1] = srcMesh->mNormals[v].y; dstNormal[2] = srcMesh->mNormals[v].z; } else { // Assimp should generate normals if they are missing, according to the postprocessing flag specified on load, // so we should never get here. assert(0); } dstNormal = (float*)((unsigned char*)dstNormal + dstMesh->vertexStride); if (srcMesh->mTangents) { dstTangent[0] = srcMesh->mTangents[v].x; dstTangent[1] = srcMesh->mTangents[v].y; dstTangent[2] = srcMesh->mTangents[v].z; } else { // TODO: generate tangents/bitangents if missing dstTangent[0] = 1.0f; dstTangent[1] = 0.0f; dstTangent[2] = 0.0f; } dstTangent = (float*)((unsigned char*)dstTangent + dstMesh->vertexStride); if (srcMesh->mBitangents) { dstBitangent[0] = srcMesh->mBitangents[v].x; dstBitangent[1] = srcMesh->mBitangents[v].y; dstBitangent[2] = srcMesh->mBitangents[v].z; } else { // TODO: generate tangents/bitangents if missing dstBitangent[0] = 0.0f; dstBitangent[1] = 1.0f; dstBitangent[2] = 0.0f; } dstBitangent = (float*)((unsigned char*)dstBitangent + dstMesh->vertexStride); } uint16_t *dstIndex = (uint16_t*)(m_pIndexData + dstMesh->indexDataByteOffset); uint16_t *dstIndexDepth = (uint16_t*)(m_pIndexDataDepth + dstMesh->indexDataByteOffset); for (unsigned int f = 0; f < srcMesh->mNumFaces; f++) { assert(srcMesh->mFaces[f].mNumIndices == 3); *dstIndex++ = srcMesh->mFaces[f].mIndices[0]; *dstIndex++ = srcMesh->mFaces[f].mIndices[1]; *dstIndex++ = srcMesh->mFaces[f].mIndices[2]; *dstIndexDepth++ = srcMesh->mFaces[f].mIndices[0]; *dstIndexDepth++ = srcMesh->mFaces[f].mIndices[1]; *dstIndexDepth++ = srcMesh->mFaces[f].mIndices[2]; } } ComputeAllBoundingBoxes(); return true; }
Ray SceneObject::emit(bool isUniformOrigin , bool isUniformDir) const { Ray ray; if(!areaValues.size()) { ray.direction = vec3f(0, 0, 0); ray.directionProb = 1; ray.color = vec3f(0, 0, 0); return ray; } if (isUniformOrigin) { float rnd = RandGenerator::genFloat()*totalArea; unsigned index = (lower_bound(areaValues.begin(), areaValues.end(), rnd)-areaValues.begin()); if(index >= areaValues.size()) index = areaValues.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); ray.originProb = weight / totalArea; } else { float rnd = RandGenerator::genFloat()*totalEnergy; unsigned index = (lower_bound(energyDensity.begin(), energyDensity.end(), rnd)-energyDensity.begin()); if(index >= energyDensity.size()) index = energyDensity.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); float prob; if (index == 0) prob = energyDensity[index] / totalEnergy; else prob = (energyDensity[index] - energyDensity[index - 1]) / totalEnergy; ray.originProb = weight * prob / areaValues[index]; } UniformSphericalSampler uniformSphericalSampler; CosineSphericalSampler cosineSphericalSampler; LocalFrame lf = ray.contactObject->getAutoGenWorldLocalFrame(ray.contactObjectTriangleID, ray.origin); if (isUniformDir) ray.direction = uniformSphericalSampler.genSample(lf); else ray.direction = cosineSphericalSampler.genSample(lf); if(ray.getContactNormal().dot(ray.direction) < 0) ray.direction = -ray.direction; ray.insideObject = scene->findInsideObject(ray, ray.contactObject); ray.current_tid = scene->getContactTreeTid(ray); ray.color = ray.getBSDF(ray); if(!emissive()) ray.color = vec3f(1, 1, 1); if (isUniformDir) ray.directionProb = uniformSphericalSampler.getProbDensity(lf , ray.direction) * 2.f; else ray.directionProb = cosineSphericalSampler.getProbDensity(lf, ray.direction); ray.directionSampleType = ray.originSampleType = Ray::RANDOM; if(!scene->usingGPU()) { Scene::ObjSourceInformation osi; NoSelfIntersectionCondition condition(scene, ray); float dist = scene->intersect(ray, osi, &condition); if(dist > 0) { ray.intersectDist = dist; ray.intersectObject = scene->objects[osi.objID]; ray.intersectObjectTriangleID = osi.triangleID; } } return ray; }
Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata, const Ogre::String &name, const Ogre::String &group, const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, const Nif::NiVertexColorProperty *vertprop, const Nif::NiZBufferProperty *zprop, const Nif::NiSpecularProperty *specprop, const Nif::NiWireframeProperty *wireprop, const Nif::NiStencilProperty *stencilprop, bool &needTangents, bool particleMaterial) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); if(!material.isNull()) return name; Ogre::Vector3 ambient(1.0f); Ogre::Vector3 diffuse(1.0f); Ogre::Vector3 specular(0.0f); Ogre::Vector3 emissive(0.0f); float glossiness = 0.0f; float alpha = 1.0f; int alphaFlags = 0; int alphaTest = 0; int vertMode = 2; //int lightMode = 1; int depthFlags = 3; // Default should be 1, but Bloodmoon's models are broken int specFlags = 0; int wireFlags = 0; int drawMode = 1; Ogre::String texName[7]; bool vertexColour = (shapedata->colors.size() != 0); // Texture if(texprop) { for(int i = 0;i < 7;i++) { if(!texprop->textures[i].inUse) continue; if(texprop->textures[i].texture.empty()) { warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name); continue; } const Nif::NiSourceTexture *st = texprop->textures[i].texture.getPtr(); if(st->external) texName[i] = Misc::ResourceHelpers::correctTexturePath(st->filename); else warn("Found internal texture, ignoring."); } Nif::ControllerPtr ctrls = texprop->controller; while(!ctrls.empty()) { if (ctrls->recType != Nif::RC_NiFlipController) // Handled in ogrenifloader warn("Unhandled texture controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } // Alpha modifiers if(alphaprop) { alphaFlags = alphaprop->flags; alphaTest = alphaprop->data.threshold; Nif::ControllerPtr ctrls = alphaprop->controller; while(!ctrls.empty()) { warn("Unhandled alpha controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } // Vertex color handling if(vertprop) { vertMode = vertprop->data.vertmode; // FIXME: Handle lightmode? //lightMode = vertprop->data.lightmode; Nif::ControllerPtr ctrls = vertprop->controller; while(!ctrls.empty()) { warn("Unhandled vertex color controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } if(zprop) { depthFlags = zprop->flags; // Depth function??? Nif::ControllerPtr ctrls = zprop->controller; while(!ctrls.empty()) { warn("Unhandled depth controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } if(specprop) { specFlags = specprop->flags; Nif::ControllerPtr ctrls = specprop->controller; while(!ctrls.empty()) { warn("Unhandled specular controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } if(wireprop) { wireFlags = wireprop->flags; Nif::ControllerPtr ctrls = wireprop->controller; while(!ctrls.empty()) { warn("Unhandled wireframe controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } if(stencilprop) { drawMode = stencilprop->data.drawMode; if (stencilprop->data.enabled) warn("Unhandled stencil test in "+name); Nif::ControllerPtr ctrls = stencilprop->controller; while(!ctrls.empty()) { warn("Unhandled stencil controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } // Material if(matprop) { ambient = matprop->data.ambient; diffuse = matprop->data.diffuse; specular = matprop->data.specular; emissive = matprop->data.emissive; glossiness = matprop->data.glossiness; alpha = matprop->data.alpha; Nif::ControllerPtr ctrls = matprop->controller; while(!ctrls.empty()) { if (ctrls->recType != Nif::RC_NiAlphaController && ctrls->recType != Nif::RC_NiMaterialColorController) warn("Unhandled material controller "+ctrls->recName+" in "+name); ctrls = ctrls->next; } } if (particleMaterial) { alpha = 1.f; // Apparently ignored, might be overridden by particle vertex colors? } { // Generate a hash out of all properties that can affect the material. size_t h = 0; boost::hash_combine(h, ambient.x); boost::hash_combine(h, ambient.y); boost::hash_combine(h, ambient.z); boost::hash_combine(h, diffuse.x); boost::hash_combine(h, diffuse.y); boost::hash_combine(h, diffuse.z); boost::hash_combine(h, alpha); boost::hash_combine(h, specular.x); boost::hash_combine(h, specular.y); boost::hash_combine(h, specular.z); boost::hash_combine(h, glossiness); boost::hash_combine(h, emissive.x); boost::hash_combine(h, emissive.y); boost::hash_combine(h, emissive.z); for(int i = 0;i < 7;i++) { if(!texName[i].empty()) { boost::hash_combine(h, texName[i]); boost::hash_combine(h, texprop->textures[i].clamp); boost::hash_combine(h, texprop->textures[i].uvSet); } } boost::hash_combine(h, drawMode); boost::hash_combine(h, vertexColour); boost::hash_combine(h, alphaFlags); boost::hash_combine(h, alphaTest); boost::hash_combine(h, vertMode); boost::hash_combine(h, depthFlags); boost::hash_combine(h, specFlags); boost::hash_combine(h, wireFlags); std::map<size_t,std::string>::iterator itr = sMaterialMap.find(h); if (itr != sMaterialMap.end()) { // a suitable material exists already - use it sh::MaterialInstance* instance = sh::Factory::getInstance().getMaterialInstance(itr->second); needTangents = !sh::retrieveValue<sh::StringValue>(instance->getProperty("normalMap"), instance).get().empty(); return itr->second; } // not found, create a new one sMaterialMap.insert(std::make_pair(h, name)); } // No existing material like this. Create a new one. sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base"); if(vertMode == 0 || !vertexColour) { instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("0"))); } else if(vertMode == 1) { instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("1"))); } else if(vertMode == 2) { instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("2"))); } else std::cerr<< "Unhandled vertex mode: "<<vertMode <<std::endl; if(specFlags) { instance->setProperty("specular", sh::makeProperty( new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); } if(wireFlags) { instance->setProperty("polygon_mode", sh::makeProperty(new sh::StringValue("wireframe"))); } if (drawMode == 1) instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("clockwise"))); else if (drawMode == 2) instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("anticlockwise"))); else if (drawMode == 3) instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("none"))); instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture])); instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); instance->setProperty("darkMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DarkTexture])); if (!texName[Nif::NiTexturingProperty::BaseTexture].empty()) { instance->setProperty("use_diffuse_map", sh::makeProperty(new sh::BooleanValue(true))); setTextureProperties(instance, "diffuseMap", texprop->textures[Nif::NiTexturingProperty::BaseTexture]); } if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) { instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); setTextureProperties(instance, "emissiveMap", texprop->textures[Nif::NiTexturingProperty::GlowTexture]); } if (!texName[Nif::NiTexturingProperty::DetailTexture].empty()) { instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true))); setTextureProperties(instance, "detailMap", texprop->textures[Nif::NiTexturingProperty::DetailTexture]); } if (!texName[Nif::NiTexturingProperty::DarkTexture].empty()) { instance->setProperty("use_dark_map", sh::makeProperty(new sh::BooleanValue(true))); setTextureProperties(instance, "darkMap", texprop->textures[Nif::NiTexturingProperty::DarkTexture]); } bool useParallax = !texName[Nif::NiTexturingProperty::BumpTexture].empty() && texName[Nif::NiTexturingProperty::BumpTexture].find("_nh.") != std::string::npos; instance->setProperty("use_parallax", sh::makeProperty(new sh::BooleanValue(useParallax))); for(int i = 0;i < 7;i++) { if(i == Nif::NiTexturingProperty::BaseTexture || i == Nif::NiTexturingProperty::DetailTexture || i == Nif::NiTexturingProperty::DarkTexture || i == Nif::NiTexturingProperty::BumpTexture || i == Nif::NiTexturingProperty::GlowTexture) continue; if(!texName[i].empty()) warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i) + " in " + name); } if (vertexColour) instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); // Override alpha flags based on our override list (transparency-overrides.cfg) if ((alphaFlags&1) && !texName[0].empty()) { NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]); if (result.first) { alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ alphaTest = result.second; depthFlags = (1<<0) | (1<<1); // depth_write on, depth_check on } } // Add transparency if NiAlphaProperty was present if((alphaFlags&1)) { std::string blend_mode; blend_mode += getBlendFactor((alphaFlags>>1)&0xf); blend_mode += " "; blend_mode += getBlendFactor((alphaFlags>>5)&0xf); instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue(blend_mode))); }
// Convert DirectX mesh to osg::Geode osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Mesh & mesh, bool flipTexture, float creaseAngle, const osgDB::ReaderWriter::Options * options) const { const DX::MeshMaterialList* meshMaterial = mesh.getMeshMaterialList(); if (!meshMaterial) return NULL; const DX::MeshNormals* meshNormals = mesh.getMeshNormals(); if (!meshNormals) { mesh.generateNormals(creaseAngle); meshNormals = mesh.getMeshNormals(); } //std::cerr << "normals=" << meshNormals << std::endl; if (!meshNormals) return NULL; const DX::MeshTextureCoords* meshTexCoords = mesh.getMeshTextureCoords(); //std::cerr << "texcoord=" << meshTexCoords << std::endl; if (!meshTexCoords) return NULL; /* * - MeshMaterialList contains a list of Material and a per-face * information with Material is to be applied to which face. * - Mesh contains a list of Vertices and a per-face information * which vertices (three or four) belong to this face. * - MeshNormals contains a list of Normals and a per-face information * which normal is used by which vertex. * - MeshTextureCoords contains a list of per-vertex texture coordinates. * * - Uses left-hand CS with Y-up, Z-into * obj_x -> osg_x * obj_y -> osg_z * obj_z -> osg_y * * - Polys are CW oriented */ std::vector<osg::Geometry*> geomList; // Texture-for-Image map std::map<std::string, osg::Texture2D*> texForImage; unsigned int i; for (i = 0; i < meshMaterial->material.size(); i++) { //std::cerr << "material " << i << std::endl; const DX::Material& mtl = meshMaterial->material[i]; osg::StateSet* state = new osg::StateSet; // Material osg::Material* material = new osg::Material; state->setAttributeAndModes(material); float alpha = mtl.faceColor.alpha; osg::Vec4 ambient(mtl.faceColor.red, mtl.faceColor.green, mtl.faceColor.blue, alpha); material->setAmbient(osg::Material::FRONT, ambient); material->setDiffuse(osg::Material::FRONT, ambient); material->setShininess(osg::Material::FRONT, mtl.power); osg::Vec4 specular(mtl.specularColor.red, mtl.specularColor.green, mtl.specularColor.blue, alpha); material->setSpecular(osg::Material::FRONT, specular); osg::Vec4 emissive(mtl.emissiveColor.red, mtl.emissiveColor.green, mtl.emissiveColor.blue, alpha); material->setEmission(osg::Material::FRONT, emissive); // Transparency? Set render hint & blending if (alpha < 1.0f) { state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); state->setMode(GL_BLEND, osg::StateAttribute::ON); } else state->setMode(GL_BLEND, osg::StateAttribute::OFF); unsigned int textureCount = mtl.texture.size(); for (unsigned int j = 0; j < textureCount; j++) { //std::cerr << "texture " << j << std::endl; // Share image/texture pairs osg::Texture2D* texture = texForImage[mtl.texture[j]]; if (!texture) { osg::Image* image = osgDB::readImageFile(mtl.texture[j],options); if (!image) continue; // Texture texture = new osg::Texture2D; texForImage[mtl.texture[j]] = texture; texture->setImage(image); texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); } state->setTextureAttributeAndModes(j, texture); } // Geometry osg::Geometry* geom = new osg::Geometry; geomList.push_back(geom); geom->setStateSet(state); // Arrays to hold vertices, normals, and texcoords. geom->setVertexArray(new osg::Vec3Array); geom->setNormalArray(new osg::Vec3Array); geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); if (textureCount) { // All texture units share the same array osg::Vec2Array* texCoords = new osg::Vec2Array; for (unsigned int j = 0; j < textureCount; j++) geom->setTexCoordArray(j, texCoords); } geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON)); } const std::vector<DX::MeshFace> & faces = mesh.getFaces(); if (faces.size() != meshMaterial->faceIndices.size()) { osg::notify(osg::FATAL)<<"Error: internal error in DirectX .x loader,"<<std::endl; osg::notify(osg::FATAL)<<" mesh->faces.size() == meshMaterial->faceIndices.size()"<<std::endl; return NULL; } // Add faces to Geometry for (i = 0; i < meshMaterial->faceIndices.size(); i++) { // Geometry for Material unsigned int mi = meshMaterial->faceIndices[i]; osg::Geometry* geom = geomList[mi]; // #pts of this face unsigned int np = faces[i].size(); ((osg::DrawArrayLengths*) geom->getPrimitiveSet(0))->push_back(np); if (np != meshNormals->faceNormals[i].size()) { osg::notify(osg::WARN)<<"DirectX loader: Error, error in normal list."<<std::endl; } osg::Vec3Array* vertexArray = (osg::Vec3Array*) geom->getVertexArray(); osg::Vec3Array* normalArray = (osg::Vec3Array*) geom->getNormalArray(); osg::Vec2Array* texCoordArray = (osg::Vec2Array*) geom->getTexCoordArray(0); // Add vertices, normals, texcoords for (unsigned int j = 0; j < np; j++) { // Convert CW to CCW order unsigned int jj = (j > 0 ? np - j : j); // Vertices unsigned int vi = faces[i][jj]; if (vertexArray) { // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup const DX::Vector & v = mesh.getVertices()[vi]; vertexArray->push_back(osg::Vec3(v.x,v.z,v.y)); } // Normals unsigned int ni = meshNormals->faceNormals[i][jj]; if (normalArray) { // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup const DX::Vector& n = meshNormals->normals[ni]; normalArray->push_back(osg::Vec3(n.x,n.z,n.y)); } // TexCoords if (texCoordArray) { const DX::Coords2d& tc = (*meshTexCoords)[vi]; osg::Vec2 uv; if (flipTexture) uv.set(tc.u, 1.0f - tc.v); // Image is upside down else uv.set(tc.u, tc.v); texCoordArray->push_back(uv); } } } // Add non-empty nodes to Geode osg::Geode* geode = new osg::Geode; for (i = 0; i < geomList.size(); i++) { osg::Geometry* geom = geomList[i]; if (((osg::Vec3Array*) geom->getVertexArray())->size()) geode->addDrawable(geom); } // Back-face culling osg::StateSet* state = new osg::StateSet; geode->setStateSet(state); osg::CullFace* cullFace = new osg::CullFace; cullFace->setMode(osg::CullFace::BACK); state->setAttributeAndModes(cullFace); return geode; }
static bool load(std::shared_ptr<CookingTask> cookingTask) { if (!cookingTask->dataSet->loadMaterials) return true; auto tid = Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PushTask("MaterialLoader : loading " + cookingTask->dataSet->filePath.getShortFileName()); if (!cookingTask->assimpScene->HasMaterials()) { Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); return true; } if (cookingTask->assimpScene->mNumMaterials <= 1) { return true; } for (unsigned int materialIndex = 1; materialIndex < cookingTask->assimpScene->mNumMaterials; ++materialIndex) { auto &aiMat = cookingTask->assimpScene->mMaterials[materialIndex]; aiColor4D diffuse(1.0f,1.0f,1.0f,1.0f); aiColor4D ambient(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D emissive(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D reflective(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D specular(1.0f, 1.0f, 1.0f, 1.0f); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_DIFFUSE, &diffuse); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_AMBIENT, &ambient); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_EMISSIVE, &emissive); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_REFLECTIVE, &reflective); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_SPECULAR, &specular); aiString diffuseTexPath; aiString ambientTexPath; aiString emissiveTexPath; aiString reflexionTexPath; aiString specularTexPath; aiString normalTexPath; aiString bumpTexPath; aiMat->GetTexture(aiTextureType_DIFFUSE, 0, &diffuseTexPath); aiMat->GetTexture(aiTextureType_AMBIENT, 0, &ambientTexPath); aiMat->GetTexture(aiTextureType_EMISSIVE, 0, &emissiveTexPath); aiMat->GetTexture(aiTextureType_REFLECTION, 0, &reflexionTexPath); aiMat->GetTexture(aiTextureType_SPECULAR, 0, &specularTexPath); aiMat->GetTexture(aiTextureType_NORMALS, 0, &normalTexPath); aiMat->Get(AI_MATKEY_TEXTURE_HEIGHT(0), bumpTexPath); auto material = std::make_shared<MaterialData>(); material->diffuse = AssimpLoader::aiColorToGlm(diffuse); material->ambient = AssimpLoader::aiColorToGlm(ambient); material->emissive = AssimpLoader::aiColorToGlm(emissive); material->reflective = AssimpLoader::aiColorToGlm(reflective); material->specular = AssimpLoader::aiColorToGlm(specular); material->diffuseTexPath = diffuseTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(diffuseTexPath) : ""; material->ambientTexPath = ambientTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(ambientTexPath) : ""; material->emissiveTexPath = emissiveTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(emissiveTexPath) : ""; material->reflectiveTexPath = reflexionTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(reflexionTexPath) : ""; material->specularTexPath = specularTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(specularTexPath) : ""; material->normalTexPath = normalTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(normalTexPath) : ""; material->bumpTexPath = bumpTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(bumpTexPath) : ""; cookingTask->texturesPath.insert(material->diffuseTexPath); cookingTask->texturesPath.insert(material->ambientTexPath); cookingTask->texturesPath.insert(material->emissiveTexPath); cookingTask->texturesPath.insert(material->reflectiveTexPath); cookingTask->texturesPath.insert(material->specularTexPath); cookingTask->texturesPath.insert(material->normalTexPath); cookingTask->texturesPath.insert(material->bumpTexPath); AssimpLoader::replaceExtension(material->diffuseTexPath, ".dds"); AssimpLoader::replaceExtension(material->ambientTexPath, ".dds"); AssimpLoader::replaceExtension(material->emissiveTexPath, ".dds"); AssimpLoader::replaceExtension(material->reflectiveTexPath, ".dds"); AssimpLoader::replaceExtension(material->specularTexPath, ".dds"); AssimpLoader::replaceExtension(material->normalTexPath, ".dds"); AssimpLoader::replaceExtension(material->bumpTexPath, ".dds"); cookingTask->materials.push_back(material); } if (cookingTask->materials.size() == 0) { Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); std::cerr << "MaterialLoader : Materials has not been loaded" << std::endl; return false; } Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); return true; }