1 /*
2 Copyright (C) 2005-2007 Feeling Software Inc.
3 Portions of the code are:
4 Copyright (C) 2005-2007 Sony Computer Entertainment America
5
6 MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8 /*
9 Based on the FS Import classes:
10 Copyright (C) 2005-2006 Feeling Software Inc
11 Copyright (C) 2005-2006 Autodesk Media Entertainment
12 MIT License: http://www.opensource.org/licenses/mit-license.php
13 */
14
15 #include "StdAfx.h"
16 #include "FCDocument/FCDocument.h"
17 #include "FCDocument/FCDGeometry.h"
18 #include "FCDocument/FCDGeometryMesh.h"
19 #include "FCDocument/FCDGeometryPolygons.h"
20 #include "FCDocument/FCDGeometryPolygonsInput.h"
21 #include "FCDocument/FCDGeometrySource.h"
22 #include "FCDocument/FCDLibrary.h"
23 #include "FUtils/FUStringConversion.h"
24
25 //
26 // FCDGeometryMesh
27 //
28
29 ImplementObjectType(FCDGeometryMesh);
30 ImplementParameterObject(FCDGeometryMesh, FCDGeometrySource, sources, new FCDGeometrySource(parent->GetDocument()));
31 ImplementParameterObject(FCDGeometryMesh, FCDGeometryPolygons, polygons, new FCDGeometryPolygons(parent->GetDocument(), parent));
32 ImplementParameterObjectNoCtr(FCDGeometryMesh, FCDGeometrySource, vertexSources);
33
FCDGeometryMesh(FCDocument * document,FCDGeometry * _parent)34 FCDGeometryMesh::FCDGeometryMesh(FCDocument* document, FCDGeometry* _parent)
35 : FCDObject(document), parent(_parent)
36 , InitializeParameterNoArg(sources)
37 , InitializeParameterNoArg(polygons)
38 , InitializeParameterNoArg(vertexSources)
39 , faceCount(0), holeCount(0), faceVertexCount(0)
40 , isConvex(true), convexify(false)
41 , InitializeParameterNoArg(convexHullOf)
42 {
43 }
44
~FCDGeometryMesh()45 FCDGeometryMesh::~FCDGeometryMesh()
46 {
47 polygons.clear();
48 sources.clear();
49 faceVertexCount = faceCount = holeCount = 0;
50 parent = NULL;
51 }
52
53 // Retrieve the parent's id
GetDaeId() const54 const fm::string& FCDGeometryMesh::GetDaeId() const
55 {
56 return parent->GetDaeId();
57 }
58
SetConvexHullOf(FCDGeometry * _geom)59 void FCDGeometryMesh::SetConvexHullOf(FCDGeometry* _geom)
60 {
61 convexHullOf = _geom->GetDaeId();
62 SetDirtyFlag();
63 }
64
FindConvexHullOfMesh() const65 const FCDGeometryMesh* FCDGeometryMesh::FindConvexHullOfMesh() const
66 {
67 const FCDGeometryMesh* mesh = this;
68 while ((mesh != NULL) && !mesh->GetConvexHullOf().empty())
69 {
70 const FCDocument* document = mesh->GetDocument();
71 const FCDGeometry* geometry = document->GetGeometryLibrary()->
72 FindDaeId(mesh->GetConvexHullOf());
73 if (geometry == NULL) return NULL;
74 mesh = geometry->GetMesh();
75 }
76 return mesh;
77 }
78
79 // Search for a data source in the geometry node
FindSourceById(const fm::string & id) const80 const FCDGeometrySource* FCDGeometryMesh::FindSourceById(const fm::string& id) const
81 {
82 const char* localId = id.c_str();
83 if (localId[0] == '#') ++localId;
84 for (const FCDGeometrySource** it = sources.begin(); it != sources.end(); ++it)
85 {
86 if ((*it)->GetDaeId() == localId) return (*it);
87 }
88 return NULL;
89 }
90
91 // Retrieve the source for the given type
FindSourceByType(FUDaeGeometryInput::Semantic type) const92 const FCDGeometrySource* FCDGeometryMesh::FindSourceByType(FUDaeGeometryInput::Semantic type) const
93 {
94 for (const FCDGeometrySource** itS = sources.begin(); itS != sources.end(); ++itS)
95 {
96 if ((*itS)->GetType() == type) return (*itS);
97 }
98 return NULL;
99 }
100
FindSourcesByType(FUDaeGeometryInput::Semantic type,FCDGeometrySourceConstList & _sources) const101 void FCDGeometryMesh::FindSourcesByType(FUDaeGeometryInput::Semantic type, FCDGeometrySourceConstList& _sources) const
102 {
103 for (const FCDGeometrySource** itS = sources.begin(); itS != sources.end(); ++itS)
104 {
105 if ((*itS)->GetType() == type) _sources.push_back(*itS);
106 }
107 }
108
FindSourceByName(const fstring & name) const109 const FCDGeometrySource* FCDGeometryMesh::FindSourceByName(const fstring& name) const
110 {
111 for (const FCDGeometrySource** itS = sources.begin(); itS != sources.end(); ++itS)
112 {
113 if ((*itS)->GetName() == name) return (*itS);
114 }
115 return NULL;
116 }
117
118 // Creates a new polygon group.
AddPolygons()119 FCDGeometryPolygons* FCDGeometryMesh::AddPolygons()
120 {
121 FCDGeometryPolygons* polys = new FCDGeometryPolygons(GetDocument(), this);
122 polygons.push_back(polys);
123
124 // Add to this new polygons all the per-vertex sources.
125 size_t vertexSourceCount = vertexSources.size();
126 for (size_t v = 0; v < vertexSourceCount; ++v)
127 {
128 polys->AddInput(vertexSources[v], 0);
129 }
130
131 SetNewChildFlag();
132 if (parent != NULL) parent->SetNewChildFlag();
133 return polys;
134 }
135
IsTriangles() const136 bool FCDGeometryMesh::IsTriangles() const
137 {
138 bool isTriangles = true;
139 for (size_t i = 0; i < polygons.size() && isTriangles; ++i)
140 {
141 isTriangles = (polygons[i]->TestPolyType() == 3);
142 }
143 return isTriangles;
144 }
145
146 // Retrieves the polygon sets that use a given material semantic
FindPolygonsByMaterial(const fstring & semantic,FCDGeometryPolygonsList & sets)147 void FCDGeometryMesh::FindPolygonsByMaterial(const fstring& semantic, FCDGeometryPolygonsList& sets)
148 {
149 size_t polygonCount = polygons.size();
150 for (size_t p = 0; p < polygonCount; ++p)
151 {
152 if (polygons[p]->GetMaterialSemantic() == semantic) sets.push_back(polygons[p]);
153 }
154 }
155
156 // Creates a new per-vertex data source
AddVertexSource(FUDaeGeometryInput::Semantic type)157 FCDGeometrySource* FCDGeometryMesh::AddVertexSource(FUDaeGeometryInput::Semantic type)
158 {
159 FCDGeometrySource* vertexSource = AddSource(type);
160 vertexSources.push_back(vertexSource);
161
162 // Add this new per-vertex data source to all the existing polygon groups, at offset 0.
163 size_t polygonsCount = polygons.size();
164 for (size_t p = 0; p < polygonsCount; ++p)
165 {
166 polygons[p]->AddInput(vertexSource, 0);
167 }
168
169 SetNewChildFlag();
170 return vertexSource;
171 }
172
173 // Sets a source as per-vertex data.
AddVertexSource(FCDGeometrySource * source)174 void FCDGeometryMesh::AddVertexSource(FCDGeometrySource* source)
175 {
176 FUAssert(source != NULL, return);
177 FUAssert(!vertexSources.contains(source), return);
178
179 // Add the source to the list of per-vertex sources.
180 vertexSources.push_back(source);
181
182 // Remove any polygon set input that uses the source.
183 size_t polygonsCount = polygons.size();
184 for (size_t p = 0; p < polygonsCount; ++p)
185 {
186 FCDGeometryPolygonsInput* input = polygons[p]->FindInput(source);
187 int32 set = (input != NULL) ? input->GetSet() : -1;
188 SAFE_RELEASE(input);
189 input = polygons[p]->AddInput(source, 0);
190 if (set > -1) input->SetSet(set);
191 }
192
193 SetNewChildFlag();
194 }
195
RemoveVertexSource(FCDGeometrySource * source)196 void FCDGeometryMesh::RemoveVertexSource(FCDGeometrySource* source)
197 {
198 FUAssert(source != NULL, return);
199 if (!vertexSources.contains(source)) return;
200
201 // Add the source to the list of per-vertex sources.
202 vertexSources.erase(source);
203 SetDirtyFlag();
204 }
205
206 // Creates a new data source
AddSource(FUDaeGeometryInput::Semantic type)207 FCDGeometrySource* FCDGeometryMesh::AddSource(FUDaeGeometryInput::Semantic type)
208 {
209 FCDGeometrySource* source = new FCDGeometrySource(GetDocument());
210 source->SetType(type);
211 sources.push_back(source);
212 SetNewChildFlag();
213 return source;
214 }
215
216 // Recalculates all the hole/vertex/face-vertex counts and offsets within the mesh and its polygons
Recalculate()217 void FCDGeometryMesh::Recalculate()
218 {
219 faceCount = holeCount = faceVertexCount = 0;
220 size_t polygonsCount = polygons.size();
221 for (size_t p = 0; p < polygonsCount; ++p)
222 {
223 FCDGeometryPolygons* polys = polygons[p];
224 polys->Recalculate();
225
226 polys->SetFaceOffset(faceCount);
227 polys->SetHoleOffset(holeCount);
228 polys->SetFaceVertexOffset(faceVertexCount);
229 faceCount += polys->GetFaceCount();
230 holeCount += polys->GetHoleCount();
231 faceVertexCount += polys->GetFaceVertexCount();
232 }
233 SetDirtyFlag();
234 }
235
Clone(FCDGeometryMesh * clone) const236 FCDGeometryMesh* FCDGeometryMesh::Clone(FCDGeometryMesh* clone) const
237 {
238 if (clone == NULL) clone = new FCDGeometryMesh(const_cast<FCDocument*>(GetDocument()), NULL);
239
240 // Copy the miscellaneous information
241 clone->convexHullOf = convexHullOf;
242 clone->isConvex = isConvex;
243 clone->convexify = convexify;
244 clone->faceCount = faceCount;
245 clone->holeCount = holeCount;
246 clone->faceVertexCount = faceVertexCount;
247
248 // Clone the sources
249 FCDGeometrySourceCloneMap cloneMap;
250 for (const FCDGeometrySource** itS = sources.begin(); itS != sources.end(); ++itS)
251 {
252 FCDGeometrySource* clonedSource = (IsVertexSource(*itS)) ? clone->AddVertexSource() : clone->AddSource();
253 (*itS)->Clone(clonedSource);
254 cloneMap.insert(*itS, clonedSource);
255 }
256
257 // Clone the polygon sets.
258 for (const FCDGeometryPolygons** itP = polygons.begin(); itP != polygons.end(); ++itP)
259 {
260 FCDGeometryPolygons* clonedPolys = clone->AddPolygons();
261 (*itP)->Clone(clonedPolys, cloneMap);
262 }
263
264 return clone;
265 }
266