diff options
Diffstat (limited to 'source/gameengine/Converter/BL_MeshDeformer.cpp')
-rw-r--r-- | source/gameengine/Converter/BL_MeshDeformer.cpp | 227 |
1 files changed, 151 insertions, 76 deletions
diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index ab31179b047..fa3b8185fe2 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -39,118 +39,193 @@ #endif #include "RAS_IPolygonMaterial.h" +#include "BL_DeformableGameObject.h" #include "BL_MeshDeformer.h" #include "BL_SkinMeshObject.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "BLI_arithb.h" #include "GEN_Map.h" #include "STR_HashedString.h" - -bool BL_MeshDeformer::Apply(RAS_IPolyMaterial *mat) +bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { - size_t i, j, index; - vecVertexArray array; - vecIndexArrays mvarray; - vecIndexArrays diarray; - - RAS_TexVert *tv; - MVert *mvert; - - // For each material - array = m_pMeshObject->GetVertexCache(mat); - mvarray = m_pMeshObject->GetMVertCache(mat); - diarray = m_pMeshObject->GetDIndexCache(mat); - - // For each array - for (i=0; i<array.size(); i++){ - // For each vertex - for (j=0; j<array[i]->size(); j++){ - tv = &((*array[i])[j]); - index = ((*diarray[i])[j]); - - mvert = &(m_bmesh->mvert[((*mvarray[i])[index])]); - tv->SetXYZ(MT_Point3(mvert->co)); + size_t i; + float *co; + + // only apply once per frame if the mesh is actually modified + if(m_pMeshObject->MeshModified() && + m_lastDeformUpdate != m_gameobj->GetLastFrame()) { + // For each material + for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + if(!mit->m_slots[(void*)m_gameobj]) + continue; + + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; + RAS_MeshSlot::iterator it; + + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { + // For each vertex + for(i=it.startvertex; i<it.endvertex; i++) { + RAS_TexVert& v = it.vertex[i]; + co = m_bmesh->mvert[v.getOrigIndex()].co; + v.SetXYZ(MT_Point3(co)); + } + } } + + m_lastDeformUpdate = m_gameobj->GetLastFrame(); + + return true; } - return true; + + return false; } BL_MeshDeformer::~BL_MeshDeformer() { if (m_transverts) - delete []m_transverts; + delete [] m_transverts; if (m_transnors) - delete []m_transnors; -}; + delete [] m_transnors; +} + +void BL_MeshDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map) +{ + void **h_obj = (*map)[m_gameobj]; + + if (h_obj) + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + else + m_gameobj = NULL; +} /** * @warning This function is expensive! */ void BL_MeshDeformer::RecalcNormals() { - int v, f; - float fnor[3], co1[3], co2[3], co3[3], co4[3]; + /* We don't normalize for performance, not doing it for faces normals + * gives area-weight normals which often look better anyway, and use + * GL_NORMALIZE so we don't have to do per vertex normalization either + * since the GPU can do it faster */ + list<RAS_MeshMaterial>::iterator mit; + RAS_MeshSlot::iterator it; + size_t i; - /* Clear all vertex normal accumulators */ - for (v =0; v<m_bmesh->totvert; v++){ - m_transnors[v]=MT_Point3(0,0,0); - } - - /* Find the face normals */ - for (f = 0; f<m_bmesh->totface; f++){ - // Make new face normal based on the transverts - MFace *mf= &((MFace*)m_bmesh->mface)[f]; - - if (mf->v3) { - for (int vl=0; vl<3; vl++){ - co1[vl]=m_transverts[mf->v1][vl]; - co2[vl]=m_transverts[mf->v2][vl]; - co3[vl]=m_transverts[mf->v3][vl]; - if (mf->v4) - co4[vl]=m_transverts[mf->v4][vl]; + /* set vertex normals to zero */ + memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert); + + /* add face normals to vertices. */ + for(mit = m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + if(!mit->m_slots[(void*)m_gameobj]) + continue; + + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; + + for(slot->begin(it); !slot->end(it); slot->next(it)) { + int nvert = (int)it.array->m_type; + + for(i=0; i<it.totindex; i+=nvert) { + RAS_TexVert& v1 = it.vertex[it.index[i]]; + RAS_TexVert& v2 = it.vertex[it.index[i+1]]; + RAS_TexVert& v3 = it.vertex[it.index[i+2]]; + RAS_TexVert *v4 = NULL; + + const float *co1 = v1.getXYZ(); + const float *co2 = v2.getXYZ(); + const float *co3 = v3.getXYZ(); + const float *co4 = NULL; + + /* compute face normal */ + float fnor[3], n1[3], n2[3]; + + if(nvert == 4) { + v4 = &it.vertex[it.index[i+3]]; + co4 = v4->getXYZ(); + + n1[0]= co1[0]-co3[0]; + n1[1]= co1[1]-co3[1]; + n1[2]= co1[2]-co3[2]; + + n2[0]= co2[0]-co4[0]; + n2[1]= co2[1]-co4[1]; + n2[2]= co2[2]-co4[2]; + } + else { + n1[0]= co1[0]-co2[0]; + n2[0]= co2[0]-co3[0]; + n1[1]= co1[1]-co2[1]; + + n2[1]= co2[1]-co3[1]; + n1[2]= co1[2]-co2[2]; + n2[2]= co2[2]-co3[2]; + } + + fnor[0]= n1[1]*n2[2] - n1[2]*n2[1]; + fnor[1]= n1[2]*n2[0] - n1[0]*n2[2]; + fnor[2]= n1[0]*n2[1] - n1[1]*n2[0]; + + /* add to vertices for smooth normals */ + float *vn1 = m_transnors[v1.getOrigIndex()]; + float *vn2 = m_transnors[v2.getOrigIndex()]; + float *vn3 = m_transnors[v3.getOrigIndex()]; + + vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2]; + vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2]; + vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2]; + + if(v4) { + float *vn4 = m_transnors[v4->getOrigIndex()]; + vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2]; + } + + /* in case of flat - just assign, the vertices are split */ + if(v1.getFlag() & RAS_TexVert::FLAT) { + v1.SetNormal(fnor); + v2.SetNormal(fnor); + v3.SetNormal(fnor); + if(v4) + v4->SetNormal(fnor); + } } + } + } + + /* assign smooth vertex normals */ + for(mit = m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + if(!mit->m_slots[(void*)m_gameobj]) + continue; + + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; + + for(slot->begin(it); !slot->end(it); slot->next(it)) { + for(i=it.startvertex; i<it.endvertex; i++) { + RAS_TexVert& v = it.vertex[i]; - /* FIXME: Use moto */ - if (mf->v4) - CalcNormFloat4(co1, co2, co3, co4, fnor); - else - CalcNormFloat(co1, co2, co3, fnor); - - /* Decide which normals are affected by this face's normal */ - m_transnors[mf->v1]+=MT_Point3(fnor); - m_transnors[mf->v2]+=MT_Point3(fnor); - m_transnors[mf->v3]+=MT_Point3(fnor); - if (mf->v4) - m_transnors[mf->v4]+=MT_Point3(fnor); + if(!(v.getFlag() & RAS_TexVert::FLAT)) + v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized() + } } } - - for (v =0; v<m_bmesh->totvert; v++){ -// float nor[3]; - - m_transnors[v]=m_transnors[v].safe_normalized(); -// nor[0]=m_transnors[v][0]; -// nor[1]=m_transnors[v][1]; -// nor[2]=m_transnors[v][2]; - - }; } void BL_MeshDeformer::VerifyStorage() { /* Ensure that we have the right number of verts assigned */ - if (m_tvtot!=m_bmesh->totvert+m_bmesh->totface){ + if (m_tvtot!=m_bmesh->totvert){ if (m_transverts) - delete []m_transverts; + delete [] m_transverts; if (m_transnors) - delete []m_transnors; + delete [] m_transnors; - m_transnors =new MT_Point3[m_bmesh->totvert+m_bmesh->totface]; - m_transverts=new float[(sizeof(*m_transverts)*m_bmesh->totvert)][3]; + m_transverts=new float[m_bmesh->totvert][3]; + m_transnors=new float[m_bmesh->totvert][3]; m_tvtot = m_bmesh->totvert; } } - + |