|
Blender
V2.59
|
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