Blender V2.61 - r43446

BL_MeshDeformer.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * Simple deformation controller that restores a mesh to its rest position
00027  */
00028 
00034 #if defined(WIN32) && !defined(FREE_WINDOWS)
00035 // This warning tells us about truncation of __long__ stl-generated names.
00036 // It can occasionally cause DevStudio to have internal compiler warnings.
00037 #pragma warning( disable : 4786 )     
00038 #endif
00039 
00040 #include "RAS_IPolygonMaterial.h"
00041 #include "BL_DeformableGameObject.h"
00042 #include "BL_MeshDeformer.h"
00043 #include "RAS_MeshObject.h"
00044 #include "DNA_mesh_types.h"
00045 #include "DNA_meshdata_types.h"
00046 
00047 #include "CTR_Map.h"
00048 #include "STR_HashedString.h"
00049 #include "BLI_math.h"
00050 
00051 bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
00052 {
00053     size_t i;
00054 
00055     // only apply once per frame if the mesh is actually modified
00056     if(m_pMeshObject->MeshModified() &&
00057        m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
00058         // For each material
00059         for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial();
00060             mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
00061             if(!mit->m_slots[(void*)m_gameobj])
00062                 continue;
00063 
00064             RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
00065             RAS_MeshSlot::iterator it;
00066 
00067             // for each array
00068             for(slot->begin(it); !slot->end(it); slot->next(it)) {
00069                 //  For each vertex
00070                 for(i=it.startvertex; i<it.endvertex; i++) {
00071                     RAS_TexVert& v = it.vertex[i];
00072                     v.SetXYZ(m_bmesh->mvert[v.getOrigIndex()].co);
00073                 }
00074             }
00075         }
00076 
00077         m_lastDeformUpdate = m_gameobj->GetLastFrame();
00078 
00079         return true;
00080     }
00081 
00082     return false;
00083 }
00084 
00085 BL_MeshDeformer::~BL_MeshDeformer()
00086 {   
00087     if (m_transverts)
00088         delete [] m_transverts;
00089     if (m_transnors)
00090         delete [] m_transnors;
00091 }
00092  
00093 void BL_MeshDeformer::ProcessReplica()
00094 {
00095     m_transverts = NULL;
00096     m_transnors = NULL;
00097     m_tvtot = 0;
00098     m_bDynamic=false;
00099     m_lastDeformUpdate = -1;
00100 }
00101 
00102 void BL_MeshDeformer::Relink(CTR_Map<class CTR_HashedPtr, void*>*map)
00103 {
00104     void **h_obj = (*map)[m_gameobj];
00105 
00106     if (h_obj)
00107         m_gameobj = (BL_DeformableGameObject*)(*h_obj);
00108     else
00109         m_gameobj = NULL;
00110 }
00111 
00115 void BL_MeshDeformer::RecalcNormals()
00116 {
00117     /* We don't normalize for performance, not doing it for faces normals
00118      * gives area-weight normals which often look better anyway, and use
00119      * GL_NORMALIZE so we don't have to do per vertex normalization either
00120      * since the GPU can do it faster */
00121     list<RAS_MeshMaterial>::iterator mit;
00122     RAS_MeshSlot::iterator it;
00123     size_t i;
00124 
00125     /* set vertex normals to zero */
00126     memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert);
00127 
00128     /* add face normals to vertices. */
00129     for(mit = m_pMeshObject->GetFirstMaterial();
00130         mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
00131         if(!mit->m_slots[(void*)m_gameobj])
00132             continue;
00133 
00134         RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
00135 
00136         for(slot->begin(it); !slot->end(it); slot->next(it)) {
00137             int nvert = (int)it.array->m_type;
00138 
00139             for(i=0; i<it.totindex; i+=nvert) {
00140                 RAS_TexVert& v1 = it.vertex[it.index[i]];
00141                 RAS_TexVert& v2 = it.vertex[it.index[i+1]];
00142                 RAS_TexVert& v3 = it.vertex[it.index[i+2]];
00143                 RAS_TexVert *v4 = NULL;
00144 
00145                 const float *co1 = m_transverts[v1.getOrigIndex()];
00146                 const float *co2 = m_transverts[v2.getOrigIndex()];
00147                 const float *co3 = m_transverts[v3.getOrigIndex()];
00148                 const float *co4 = NULL;
00149                 
00150                 /* compute face normal */
00151                 float fnor[3], n1[3], n2[3];
00152 
00153                 if(nvert == 4) {
00154                     v4 = &it.vertex[it.index[i+3]];
00155                     co4 = m_transverts[v4->getOrigIndex()];
00156 
00157                     n1[0]= co1[0]-co3[0];
00158                     n1[1]= co1[1]-co3[1];
00159                     n1[2]= co1[2]-co3[2];
00160 
00161                     n2[0]= co2[0]-co4[0];
00162                     n2[1]= co2[1]-co4[1];
00163                     n2[2]= co2[2]-co4[2];
00164                 }
00165                 else {
00166                     n1[0]= co1[0]-co2[0];
00167                     n2[0]= co2[0]-co3[0];
00168                     n1[1]= co1[1]-co2[1];
00169 
00170                     n2[1]= co2[1]-co3[1];
00171                     n1[2]= co1[2]-co2[2];
00172                     n2[2]= co2[2]-co3[2];
00173                 }
00174 
00175                 fnor[0]= n1[1]*n2[2] - n1[2]*n2[1];
00176                 fnor[1]= n1[2]*n2[0] - n1[0]*n2[2];
00177                 fnor[2]= n1[0]*n2[1] - n1[1]*n2[0];
00178                 normalize_v3(fnor);
00179 
00180                 /* add to vertices for smooth normals */
00181                 float *vn1 = m_transnors[v1.getOrigIndex()];
00182                 float *vn2 = m_transnors[v2.getOrigIndex()];
00183                 float *vn3 = m_transnors[v3.getOrigIndex()];
00184 
00185                 vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2];
00186                 vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2];
00187                 vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2];
00188 
00189                 if(v4) {
00190                     float *vn4 = m_transnors[v4->getOrigIndex()];
00191                     vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2];
00192                 }
00193 
00194                 /* in case of flat - just assign, the vertices are split */
00195                 if(v1.getFlag() & RAS_TexVert::FLAT) {
00196                     v1.SetNormal(fnor);
00197                     v2.SetNormal(fnor);
00198                     v3.SetNormal(fnor);
00199                     if(v4)
00200                         v4->SetNormal(fnor);
00201                 }
00202             }
00203         }
00204     }
00205 
00206     /* assign smooth vertex normals */
00207     for(mit = m_pMeshObject->GetFirstMaterial();
00208         mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
00209         if(!mit->m_slots[(void*)m_gameobj])
00210             continue;
00211 
00212         RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
00213 
00214         for(slot->begin(it); !slot->end(it); slot->next(it)) {
00215             for(i=it.startvertex; i<it.endvertex; i++) {
00216                 RAS_TexVert& v = it.vertex[i];
00217 
00218                 if(!(v.getFlag() & RAS_TexVert::FLAT))
00219                     v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized()
00220             }
00221         }
00222     }
00223 }
00224 
00225 void BL_MeshDeformer::VerifyStorage()
00226 {
00227     /* Ensure that we have the right number of verts assigned */
00228     if (m_tvtot!=m_bmesh->totvert){
00229         if (m_transverts)
00230             delete [] m_transverts;
00231         if (m_transnors)
00232             delete [] m_transnors;
00233         
00234         m_transverts=new float[m_bmesh->totvert][3];
00235         m_transnors=new float[m_bmesh->totvert][3];
00236         m_tvtot = m_bmesh->totvert;
00237     }
00238 }
00239