4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
28 * Simple deformation controller that restores a mesh to its rest position
31 #if defined(WIN32) && !defined(FREE_WINDOWS)
32 // This warning tells us about truncation of __long__ stl-generated names.
33 // It can occasionally cause DevStudio to have internal compiler warnings.
34 #pragma warning( disable : 4786 )
37 #include "RAS_IPolygonMaterial.h"
38 #include "BL_DeformableGameObject.h"
39 #include "BL_MeshDeformer.h"
40 #include "RAS_MeshObject.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
45 #include "STR_HashedString.h"
48 bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
52 // only apply once per frame if the mesh is actually modified
53 if(m_pMeshObject->MeshModified() &&
54 m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
56 for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial();
57 mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
58 if(!mit->m_slots[(void*)m_gameobj])
61 RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
62 RAS_MeshSlot::iterator it;
65 for(slot->begin(it); !slot->end(it); slot->next(it)) {
67 for(i=it.startvertex; i<it.endvertex; i++) {
68 RAS_TexVert& v = it.vertex[i];
69 v.SetXYZ(m_bmesh->mvert[v.getOrigIndex()].co);
74 m_lastDeformUpdate = m_gameobj->GetLastFrame();
82 BL_MeshDeformer::~BL_MeshDeformer()
85 delete [] m_transverts;
87 delete [] m_transnors;
90 void BL_MeshDeformer::ProcessReplica()
96 m_lastDeformUpdate = -1;
99 void BL_MeshDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
101 void **h_obj = (*map)[m_gameobj];
104 m_gameobj = (BL_DeformableGameObject*)(*h_obj);
110 * @warning This function is expensive!
112 void BL_MeshDeformer::RecalcNormals()
114 /* We don't normalize for performance, not doing it for faces normals
115 * gives area-weight normals which often look better anyway, and use
116 * GL_NORMALIZE so we don't have to do per vertex normalization either
117 * since the GPU can do it faster */
118 list<RAS_MeshMaterial>::iterator mit;
119 RAS_MeshSlot::iterator it;
122 /* set vertex normals to zero */
123 memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert);
125 /* add face normals to vertices. */
126 for(mit = m_pMeshObject->GetFirstMaterial();
127 mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
128 if(!mit->m_slots[(void*)m_gameobj])
131 RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
133 for(slot->begin(it); !slot->end(it); slot->next(it)) {
134 int nvert = (int)it.array->m_type;
136 for(i=0; i<it.totindex; i+=nvert) {
137 RAS_TexVert& v1 = it.vertex[it.index[i]];
138 RAS_TexVert& v2 = it.vertex[it.index[i+1]];
139 RAS_TexVert& v3 = it.vertex[it.index[i+2]];
140 RAS_TexVert *v4 = NULL;
142 const float *co1 = m_transverts[v1.getOrigIndex()];
143 const float *co2 = m_transverts[v2.getOrigIndex()];
144 const float *co3 = m_transverts[v3.getOrigIndex()];
145 const float *co4 = NULL;
147 /* compute face normal */
148 float fnor[3], n1[3], n2[3];
151 v4 = &it.vertex[it.index[i+3]];
152 co4 = m_transverts[v4->getOrigIndex()];
154 n1[0]= co1[0]-co3[0];
155 n1[1]= co1[1]-co3[1];
156 n1[2]= co1[2]-co3[2];
158 n2[0]= co2[0]-co4[0];
159 n2[1]= co2[1]-co4[1];
160 n2[2]= co2[2]-co4[2];
163 n1[0]= co1[0]-co2[0];
164 n2[0]= co2[0]-co3[0];
165 n1[1]= co1[1]-co2[1];
167 n2[1]= co2[1]-co3[1];
168 n1[2]= co1[2]-co2[2];
169 n2[2]= co2[2]-co3[2];
172 fnor[0]= n1[1]*n2[2] - n1[2]*n2[1];
173 fnor[1]= n1[2]*n2[0] - n1[0]*n2[2];
174 fnor[2]= n1[0]*n2[1] - n1[1]*n2[0];
177 /* add to vertices for smooth normals */
178 float *vn1 = m_transnors[v1.getOrigIndex()];
179 float *vn2 = m_transnors[v2.getOrigIndex()];
180 float *vn3 = m_transnors[v3.getOrigIndex()];
182 vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2];
183 vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2];
184 vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2];
187 float *vn4 = m_transnors[v4->getOrigIndex()];
188 vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2];
191 /* in case of flat - just assign, the vertices are split */
192 if(v1.getFlag() & RAS_TexVert::FLAT) {
203 /* assign smooth vertex normals */
204 for(mit = m_pMeshObject->GetFirstMaterial();
205 mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
206 if(!mit->m_slots[(void*)m_gameobj])
209 RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
211 for(slot->begin(it); !slot->end(it); slot->next(it)) {
212 for(i=it.startvertex; i<it.endvertex; i++) {
213 RAS_TexVert& v = it.vertex[i];
215 if(!(v.getFlag() & RAS_TexVert::FLAT))
216 v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized()
222 void BL_MeshDeformer::VerifyStorage()
224 /* Ensure that we have the right number of verts assigned */
225 if (m_tvtot!=m_bmesh->totvert){
227 delete [] m_transverts;
229 delete [] m_transnors;
231 m_transverts=new float[m_bmesh->totvert][3];
232 m_transnors=new float[m_bmesh->totvert][3];
233 m_tvtot = m_bmesh->totvert;