예제 #1
0
/*!
SLAssimpImporter::loadMesh creates a new SLMesh an copies the meshs vertex data and
triangle face indices. Normals & tangents are not loaded. They are calculated
in SLMesh.
*/
SLMesh* SLAssimpImporter::loadMesh(aiMesh *mesh)
{
    // Count first the NO. of triangles in the mesh
    SLuint numTriangles = 0;
    for(unsigned int i = 0; i <  mesh->mNumFaces; ++i)
        if(mesh->mFaces[i].mNumIndices == 3)
            numTriangles++;

    // We only load meshes that contain triangles
    if (numTriangles==0 || mesh->mNumVertices==0)
        return nullptr; 

    // create a new mesh. 
    // The mesh pointer is added automatically to the SLScene::meshes vector.
    SLstring name = mesh->mName.data;
    SLMesh *m = new SLMesh(name.empty() ? "Imported Mesh" : name);

    // create position & normal vector
    m->P.clear(); m->P.resize(mesh->mNumVertices);

    // create normal vector
    if (mesh->HasNormals())
    {   m->N.clear();
        m->N.resize(m->P.size());
    }

    // allocate texCoord vector if needed
    if (mesh->HasTextureCoords(0))
    {   m->Tc.clear();
        m->Tc.resize(m->P.size());
    }

    // copy vertex positions & texCoord
    for(SLuint i = 0; i < m->P.size(); ++i)
    {   m->P[i].set(mesh->mVertices[i].x, 
        mesh->mVertices[i].y, 
        mesh->mVertices[i].z);
        if (m->N.size())
            m->N[i].set(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
        if (m->Tc.size())
            m->Tc[i].set(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
    }

    // create face index vector
    if (m->P.size() < 65536)
    {   m->I16.clear();
        m->I16.resize(mesh->mNumFaces * 3);

        // load face triangle indices only
        SLuint j = 0;
        for(SLuint i = 0; i <  mesh->mNumFaces; ++i)
        {   if(mesh->mFaces[i].mNumIndices == 3)
            {   m->I16[j++] = mesh->mFaces[i].mIndices[0];
                m->I16[j++] = mesh->mFaces[i].mIndices[1];
                m->I16[j++] = mesh->mFaces[i].mIndices[2];
            }
        }
    } else 
    {   m->I32.clear();
        m->I32.resize(mesh->mNumFaces * 3);

        // load face triangle indices only
        SLuint j = 0;
        for(SLuint i = 0; i <  mesh->mNumFaces; ++i)
        {  if(mesh->mFaces[i].mNumIndices == 3)
            {   m->I32[j++] = mesh->mFaces[i].mIndices[0];
                m->I32[j++] = mesh->mFaces[i].mIndices[1];
                m->I32[j++] = mesh->mFaces[i].mIndices[2];
            }
        }
    }

    if (!m->N.size())
        m->calcNormals();

    // load joints
    if (mesh->HasBones())
    {
        _skinnedMeshes.push_back(m);
        m->skeleton(_skeleton);

        m->Ji.resize(m->P.size());
        m->Jw.resize(m->P.size());
        
        // make sure to initialize the weights with 0 vectors
        std::fill(m->Ji.begin(), m->Ji.end(), SLVec4f(0, 0, 0, 0));
        std::fill(m->Jw.begin(), m->Jw.end(), SLVec4f(0, 0, 0, 0));

        for (SLuint i = 0; i < mesh->mNumBones; i++)
        {
            aiBone* joint = mesh->mBones[i];
            SLJoint* slJoint = _skeleton->getJoint(joint->mName.C_Str());
            
            // @todo On OSX it happens from time to time that slJoint is nullptr
            if (slJoint)
            {
                SLuint jointId = slJoint->id();

                for (SLuint j = 0; j < joint->mNumWeights; j++)
                {
                    // add the weight
                    SLuint vertId = joint->mWeights[j].mVertexId;
                    SLfloat weight = joint->mWeights[j].mWeight;

                    m->addWeight(vertId, jointId, weight);

                    // check if the bones max radius changed
                    // @todo this is very specific to this loaded mesh,
                    //       when we add a skeleton instances class this radius
                    //       calculation has to be done on the instance!
                    slJoint->calcMaxRadius(SLVec3f(mesh->mVertices[vertId].x,
                                                   mesh->mVertices[vertId].y,
                                                   mesh->mVertices[vertId].z));
                }
            }
            else
            {   SL_LOG("Failed to load joint of skeleton in SLAssimpImporter::loadMesh: %s\n", joint->mName.C_Str());
                return nullptr;
            }
        }

    }
    return m;
}
예제 #2
0
/*!
SLAssimpImporter::loadMaterial loads the AssImp material an returns the SLMaterial.
The materials and textures are added to the SLScene material and texture 
vectors.
*/
SLMaterial* SLAssimpImporter::loadMaterial(SLint index, 
                                           aiMaterial *material,
                                           SLstring modelPath)
{
    // Get the materials name
    aiString matName;
    material->Get(AI_MATKEY_NAME, matName);
    SLstring name = matName.data;
    if (name.empty()) name = "Import Material";
   
    // Create SLMaterial instance. It is also added to the SLScene::_materials vector
    SLMaterial* mat = new SLMaterial(name.c_str());

    // set the texture types to import into our material
    const SLint		textureCount = 4;
    aiTextureType	textureTypes[textureCount];
    textureTypes[0] = aiTextureType_DIFFUSE;
    textureTypes[1] = aiTextureType_NORMALS;
    textureTypes[2] = aiTextureType_SPECULAR;
    textureTypes[3] = aiTextureType_HEIGHT;
   
    // load all the textures for this material and add it to the material vector
    for(SLint i = 0; i < textureCount; ++i) 
    {   if(material->GetTextureCount(textureTypes[i]) > 0) 
        {   aiString aipath;
            material->GetTexture(textureTypes[i], 0, &aipath, nullptr, nullptr, nullptr, nullptr, nullptr);
            SLTextureType texType = textureTypes[i]==aiTextureType_DIFFUSE  ? TT_color :
                                textureTypes[i]==aiTextureType_NORMALS  ? TT_normal :
                                textureTypes[i]==aiTextureType_SPECULAR ? TT_gloss :
                                textureTypes[i]==aiTextureType_HEIGHT   ? TT_height : 
                                TT_unknown;
            SLstring texFile = checkFilePath(modelPath, aipath.data);
            SLGLTexture* tex = loadTexture(texFile, texType);
            mat->textures().push_back(tex);
        }
    }
   
    // get color data
    aiColor3D ambient, diffuse, specular, emissive;
    SLfloat shininess, refracti, reflectivity, opacity;
    material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
    material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
    material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
    material->Get(AI_MATKEY_COLOR_EMISSIVE, emissive);
    material->Get(AI_MATKEY_SHININESS, shininess);
    material->Get(AI_MATKEY_REFRACTI, refracti);
    material->Get(AI_MATKEY_REFLECTIVITY, reflectivity);
    material->Get(AI_MATKEY_OPACITY, opacity);

    // increase shininess if specular color is not low.
    // The material will otherwise be to bright
    if (specular.r > 0.5f &&
        specular.g > 0.5f &&
        specular.b > 0.5f &&
        shininess < 0.01f)
        shininess = 10.0f;

    // set color data
    mat->ambient(SLCol4f(ambient.r, ambient.g, ambient.b));
    mat->diffuse(SLCol4f(diffuse.r, diffuse.g, diffuse.b));
    mat->specular(SLCol4f(specular.r, specular.g, specular.b));
    mat->emission(SLCol4f(emissive.r, emissive.g, emissive.b));
    mat->shininess(shininess);
    //mat->kr(reflectivity);
    //mat->kt(1.0f-opacity);
    //mat->kn(refracti);

    return mat;
}