Panda3D
physxClothNode.cxx
1 // Filename: physxClothNode.cxx
2 // Created by: enn0x (05Apr10)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "physxClothNode.h"
16 #include "physxCloth.h"
17 #include "physxFileStream.h"
18 
19 #include "geomVertexFormat.h"
20 #include "geomVertexWriter.h"
21 
22 TypeHandle PhysxClothNode::_type_handle;
23 
24 ////////////////////////////////////////////////////////////////////
25 // Function: PhysxClothNode::allocate
26 // Access: Public
27 // Description:
28 ////////////////////////////////////////////////////////////////////
29 void PhysxClothNode::
30 allocate(PhysxCloth *cloth) {
31 
32  _cloth = cloth;
33 
34  // Retrieve number of vertices and triangles the hard way
35  NxClothMeshDesc meshDesc;
36  _cloth->ptr()->getClothMesh()->saveToDesc(meshDesc);
37 
38  NxU32 numVertices = meshDesc.numVertices;
39  NxU32 numTriangles = meshDesc.numTriangles;
40 
41  NxReal factor = 1.0f; // TODO: max(1.0f, factor);
42 
43  // Reserve more memory for vertices than the initial mesh takes because
44  // tearing creates new vertices
45  NxU32 maxVertices = factor * numVertices;
46  _mesh.verticesPosBegin = (NxVec3 *)malloc(sizeof(NxVec3) * maxVertices);
47  _mesh.verticesNormalBegin = (NxVec3 *)malloc(sizeof(NxVec3) * maxVertices);
48  _mesh.verticesPosByteStride = sizeof(NxVec3);
49  _mesh.verticesNormalByteStride = sizeof(NxVec3);
50  _mesh.maxVertices = maxVertices;
51  _mesh.numVerticesPtr = (NxU32 *)malloc(sizeof(NxU32));
52 
53  // The number of triangles is constant, even if the cloth is torn
54  NxU32 maxIndices = 3 * numTriangles;
55  _mesh.indicesBegin = (NxU32 *)malloc(sizeof(NxU32) * maxIndices);
56  _mesh.indicesByteStride = sizeof(NxU32);
57  _mesh.maxIndices = maxIndices;
58  _mesh.numIndicesPtr = (NxU32 *)malloc(sizeof(NxU32));
59 
60  NxU32 maxParentIndices = maxVertices;
61  _mesh.parentIndicesBegin = (NxU32 *)malloc(sizeof(NxU32)*maxParentIndices);
62  _mesh.parentIndicesByteStride = sizeof(NxU32);
63  _mesh.maxParentIndices = maxParentIndices;
64  _mesh.numParentIndicesPtr = (NxU32 *)malloc(sizeof(NxU32));
65 
66  *(_mesh.numVerticesPtr) = 0;
67  *(_mesh.numIndicesPtr) = 0;
68 
69  _cloth->ptr()->setMeshData(_mesh);
70 }
71 
72 ////////////////////////////////////////////////////////////////////
73 // Function: PhysxClothNode::update
74 // Access: Public
75 // Description:
76 ////////////////////////////////////////////////////////////////////
77 void PhysxClothNode::
78 update() {
79 
80  NxU32 numVertices = *(_mesh.numVerticesPtr);
81 
82  if (numVertices == _numVertices) {
83  update_geom();
84  }
85  else {
86  update_texcoords();
87  create_geom();
88  _numVertices = numVertices;
89  }
90 }
91 
92 ////////////////////////////////////////////////////////////////////
93 // Function: PhysxClothNode::create_geom
94 // Access: Private
95 // Description:
96 ////////////////////////////////////////////////////////////////////
97 void PhysxClothNode::
98 create_geom() {
99 
100  _prim->clear_vertices();
101 
102  GeomVertexWriter vwriter = GeomVertexWriter(_vdata, InternalName::get_vertex());
103  GeomVertexWriter nwriter = GeomVertexWriter(_vdata, InternalName::get_normal());
104  GeomVertexWriter twriter = GeomVertexWriter(_vdata, InternalName::get_texcoord());
105 
106  // Vertices and normals
107  NxU32 numVertices = *(_mesh.numVerticesPtr);
108  NxVec3 *v = (NxVec3 *)_mesh.verticesPosBegin;
109  NxVec3 *n = (NxVec3 *)_mesh.verticesNormalBegin;
110 
111  for (unsigned int i=0; i < numVertices; i++) {
112  vwriter.add_data3f(v->x, v->y, v->z);
113  v++;
114  nwriter.add_data3f(n->x, n->y, n->z);
115  n++;
116  }
117 
118  // Texture coordinates
119  NxReal tex_u;
120  NxReal tex_v;
121 
122  if (_texcoords) {
123  for (unsigned int i=0; i < numVertices; i++) {
124  tex_u = _texcoords[2*i];
125  tex_v = _texcoords[2*i+1];
126  twriter.add_data2f(tex_u, tex_v);
127  }
128  }
129 
130  // Indices
131  NxU32 numIndices = *(_mesh.numIndicesPtr);
132  NxU32 *idx = (NxU32 *)_mesh.indicesBegin;
133 
134  for (unsigned int i=0; i < numIndices; i++) {
135  _prim->add_vertex(*idx);
136  idx++;
137  }
138 
139  _prim->close_primitive();
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 // Function: PhysxClothNode::update_geom
144 // Access: Private
145 // Description:
146 ////////////////////////////////////////////////////////////////////
147 void PhysxClothNode::
148 update_geom() {
149 
150  GeomVertexWriter vwriter = GeomVertexWriter(_vdata, InternalName::get_vertex());
151  GeomVertexWriter nwriter = GeomVertexWriter(_vdata, InternalName::get_normal());
152 
153  NxU32 numVertices = *(_mesh.numVerticesPtr);
154  NxVec3 *v = (NxVec3 *)_mesh.verticesPosBegin;
155  NxVec3 *n = (NxVec3 *)_mesh.verticesNormalBegin;
156 
157  for (unsigned int i=0; i < numVertices; i++) {
158  vwriter.set_data3f(v->x, v->y, v->z);
159  v++;
160  nwriter.set_data3f(n->x, n->y, n->z);
161  n++;
162  }
163 }
164 
165 ////////////////////////////////////////////////////////////////////
166 // Function: PhysxClothNode::update_texcoords
167 // Access: Private
168 // Description:
169 ////////////////////////////////////////////////////////////////////
170 void PhysxClothNode::
171 update_texcoords() {
172 
173  if (!_texcoords) {
174  return;
175  }
176 
177  NxU32 numVertices = *(_mesh.numVerticesPtr);
178  NxU32 *parent = (NxU32 *)_mesh.parentIndicesBegin + _numTexcoords;
179 
180  for (NxU32 i=_numTexcoords; i < numVertices; i++, parent++) {
181  _texcoords[2*i] = _texcoords[2*(*parent)];
182  _texcoords[2*i+1] = _texcoords[2*(*parent)+1];
183  }
184 
185  _numTexcoords = numVertices;
186 }
187 
188 ////////////////////////////////////////////////////////////////////
189 // Function: PhysxClothNode::set_texcoords
190 // Access: Published
191 // Description:
192 ////////////////////////////////////////////////////////////////////
193 bool PhysxClothNode::
194 set_texcoords(const Filename &filename) {
195 
196  if (filename.empty()) {
197  return false;
198  }
199 
200  Filename fn(filename);
201  fn.resolve_filename(get_model_path());
202 
203  if (!filename.exists()) {
204  return false;
205  }
206 
207  PhysxFileStream fs(filename.c_str(), true);
208 
209  fs.readByte(); // N
210  fs.readByte(); // X
211  fs.readByte(); // X
212  fs.readByte(); // 1
213  fs.readByte(); // T
214  fs.readByte(); // E
215  fs.readByte(); // X
216  fs.readByte(); // C
217  fs.readByte(); // 1
218 
219  _numTexcoords = fs.readDword();
220  _texcoords = new float[2 * _numTexcoords];
221 
222  for (unsigned int i=0; i<_numTexcoords; i++) {
223  _texcoords[2*i] = fs.readFloat();
224  _texcoords[2*i+1] = fs.readFloat();
225  }
226 
227  return true;
228 }
229 
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_data2f(float x, float y)
Sets the write row to a particular 2-component value, and advances the write row. ...
void set_data3f(float x, float y, float z)
Sets the write row to a particular 3-component value, and advances the write row. ...
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
void add_data3f(float x, float y, float z)
Sets the write row to a particular 3-component value, and advances the write row. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356