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