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