1 /***************************************************************************
2                           Shape3D.cpp  -  description
3                              -------------------
4     begin                : Wed Jan 26 2000
5     copyright            : (C) 2000 by Henrik Enqvist
6     email                : henqvist@excite.com
7  ***************************************************************************/
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 
13 #include "Private.h"
14 #include "Shape3D.h"
15 #include "Polygon.h"
16 
Shape3D(int v,int p)17 Shape3D::Shape3D(int v, int p) {
18 	m_iProperties = 0;
19 	p_Parent = NULL;
20 	m_vPolygon.reserve(p);
21 
22 	m_vVtxSrc.reserve(v);
23 	m_vVtxTrans.reserve(v);
24 	m_vVtxAlign.reserve(v);
25 
26 	m_vNmlSrc.reserve(v);
27 	m_vNmlTrans.reserve(v);
28 	m_vNmlAlign.reserve(v);
29 
30 	m_vLight.reserve(v);
31 	m_vSpecular.reserve(v);
32 
33 	m_vColor.reserve(v);
34 	m_vLitColor.reserve(v);
35 	m_vTexCoord.reserve(v);
36 
37 	m_Texture = NULL;
38 }
39 
~Shape3D()40 Shape3D::~Shape3D() {
41 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
42 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
43 	for ( ; iter != end; iter++) {
44 		delete (*iter);
45 	}
46 	m_vPolygon.clear();
47 }
48 
setPolygonProperty(int p)49 void Shape3D::setPolygonProperty(int p) {
50 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
51 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
52 	for ( ; iter != end; iter++) {
53 		(*iter)->setProperty(p);
54 	}
55 }
56 
unsetPolygonProperty(int p)57 void Shape3D::unsetPolygonProperty(int p) {
58 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
59 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
60 	for ( ; iter != end; iter++) {
61 		(*iter)->unsetProperty(p);
62 	}
63 }
64 
setProperty(int p)65 void Shape3D::setProperty(int p) {
66 	m_iProperties |= p;
67 }
68 
unsetProperty(int p)69 void Shape3D::unsetProperty(int p) {
70 	m_iProperties -= (m_iProperties & p);
71 }
72 
setParent(Group * p)73 void Shape3D::setParent(Group* p) {
74 	p_Parent = p;
75 }
76 
setTexture(EmTexture * tex)77 void Shape3D::setTexture(EmTexture* tex) {
78 	m_Texture = tex;
79 }
80 
81 /*
82  * Adds a vertex to this shape. The index of the vertices will be the
83  * same as the order they are added.
84  */
add(float x,float y,float z)85 int Shape3D::add(float x, float y, float z) {
86 	this->add(x, y, z, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f);
87 	return m_vVtxSrc.size() - 1;
88 }
89 
add(float x,float y,float z,float r,float g,float b,float a,float u,float v)90 int Shape3D::add(float x, float y, float z, float r, float g, float b, float a, float u, float v) {
91 	EM_COUT("Shape3D::add() "<< x <<" "<< y <<" "<< z, 0);
92 
93 	Vertex3D vtx;
94 	vtx.x = x;
95 	vtx.y = y;
96 	vtx.z = z;
97 	m_vVtxSrc.push_back(vtx);
98 	// Add dummy values to trans and align, i.e. allocate space
99 	m_vVtxTrans.push_back(vtx);
100 	m_vVtxAlign.push_back(vtx);
101 	// Add dummy values to normals, i.e. allocate space
102 	m_vNmlSrc.push_back(vtx);
103 	m_vNmlTrans.push_back(vtx);
104 	m_vNmlAlign.push_back(vtx);
105 
106 	Color color = {1.0f, 1.0f, 1.0f, 1.0f};
107 	m_vLight.push_back(color);
108 	m_vSpecular.push_back(color);
109 
110 	color.r = r;
111 	color.g = g;
112 	color.b = b;
113 	color.a = a;
114 	m_vColor.push_back(color);
115 	m_vLitColor.push_back(color);
116 	TexCoord texcoord;
117 	texcoord.u = u;
118 	texcoord.v = v;
119 	m_vTexCoord.push_back(texcoord);
120 
121 	return m_vVtxSrc.size() - 1;
122 }
123 
addAt(int index,float x,float y,float z,float r,float g,float b,float a,float u,float v)124 int Shape3D::addAt(int index, float x, float y, float z,
125 									 float r, float g, float b, float a, float u, float v) {
126 	if (index < 0 || index >= (signed)m_vVtxSrc.size()) {
127 		return this->add(x, y, z, r, g, b, a, u, v);
128 	}
129 
130 	Vertex3D vtx;
131 	vtx.x = x;
132 	vtx.y = y;
133 	vtx.z = z;
134 	m_vVtxSrc.insert(m_vVtxSrc.begin()+index, vtx);
135 	// Add dummy values to trans and align, i.e. allocate space
136 	m_vVtxTrans.insert(m_vVtxTrans.begin()+index, vtx);
137 	m_vVtxAlign.insert(m_vVtxAlign.begin()+index, vtx);
138 	// Add dummy values to normals, i.e. allocate space
139 	m_vNmlSrc.insert(m_vNmlSrc.begin()+index, vtx);
140 	m_vNmlTrans.insert(m_vNmlTrans.begin()+index, vtx);
141 	m_vNmlAlign.insert(m_vNmlAlign.begin()+index, vtx);
142 
143 	Color color = {1.0f, 1.0f, 1.0f, 1.0f};
144 	m_vLight.insert(m_vLight.begin()+index, color);
145 	m_vSpecular.insert(m_vSpecular.begin()+index, color);
146 
147 	color.r = r;
148 	color.g = g;
149 	color.b = b;
150 	color.a = a;
151 	m_vColor.insert(m_vColor.begin()+index, color);
152 	m_vLitColor.insert(m_vLitColor.begin()+index, color);
153 	TexCoord texcoord;
154 	texcoord.u = u;
155 	texcoord.v = v;
156 	m_vTexCoord.insert(m_vTexCoord.begin()+index, texcoord);
157 
158 	return index;
159 }
160 
161 
162 
getVertex3D(int index)163 Vertex3D * Shape3D::getVertex3D(int index) {
164 	if ( index < 0 || index >= (signed)m_vVtxSrc.size() ) {
165 		return NULL;
166 	}
167 	return &(m_vVtxSrc[index]);
168 }
169 
getVertex3DSize()170 int Shape3D::getVertex3DSize() {
171 	return m_vVtxSrc.size();
172 }
173 
getVertex3DIndex(Vertex3D * vtx)174 int Shape3D::getVertex3DIndex(Vertex3D * vtx) {
175 	if (vtx == NULL) return -1;
176 	vector<Vertex3D>::iterator iter = m_vVtxSrc.begin();
177 	vector<Vertex3D>::iterator end = m_vVtxSrc.end();
178 	for (int a=0; iter != end; iter++, a++) {
179 		if (&(*iter) == vtx) return a;
180 	}
181 	return -1;
182 }
183 
getVertex3DIndex(TexCoord * tex)184 int Shape3D::getVertex3DIndex(TexCoord * tex) {
185 	if (tex == NULL) return -1;
186 	vector<TexCoord>::iterator iter = m_vTexCoord.begin();
187 	vector<TexCoord>::iterator end = m_vTexCoord.end();
188 	for (int a=0; iter != end; iter++, a++) {
189 		if (&(*iter) == tex) return a;
190 	}
191 	return -1;
192 }
193 
getColor(int index)194 Color * Shape3D::getColor(int index) {
195   if (index < 0 || index >= (signed)m_vColor.size()) {
196     return NULL;
197   }
198   return &(m_vColor[index]);
199 }
200 
setColor(int index,float r,float g,float b,float a)201 void Shape3D::setColor(int index, float r, float g, float b, float a) {
202   if (index < 0 || index >= (signed)m_vColor.size()) {
203     return;
204   }
205   m_vColor[index].r = EM_MAX(EM_MIN(r, 1.0f), 0.0f);
206   m_vColor[index].g = EM_MAX(EM_MIN(g, 1.0f), 0.0f);
207   m_vColor[index].b = EM_MAX(EM_MIN(b, 1.0f), 0.0f);
208   m_vColor[index].a = EM_MAX(EM_MIN(a, 1.0f), 0.0f);
209 }
210 
getTexCoord(int index)211 TexCoord * Shape3D::getTexCoord(int index) {
212 	if (index < 0 || index >= (signed)m_vTexCoord.size()) {
213 		return NULL;
214 	}
215 	return &(m_vTexCoord[index]);
216 }
217 
setTexCoord(int index,float u,float v)218 void Shape3D::setTexCoord(int index, float u, float v) {
219 	if (index < 0 || index >= (signed)m_vTexCoord.size()) {
220 		return;
221 	}
222 	m_vTexCoord[index].u = u;
223 	m_vTexCoord[index].v = v;
224 }
225 
removeLooseVertex3D(int vtxindex)226 bool Shape3D::removeLooseVertex3D(int vtxindex) {
227 	if (vtxindex < 0 || vtxindex >= (signed)m_vVtxSrc.size()) return false;
228 	// check that the vertex is not included in any polygon
229 	vector<Polygon3D*>::iterator polyiter = m_vPolygon.begin();
230 	vector<Polygon3D*>::iterator polyend = m_vPolygon.end();
231 	for (; polyiter != polyend; ++polyiter) {
232 		if ((*polyiter)->includes(vtxindex) >= 0) return false;
233 	}
234 
235  	m_vVtxSrc.erase(m_vVtxSrc.begin()+vtxindex);
236  	m_vVtxTrans.erase(m_vVtxTrans.begin()+vtxindex);
237  	m_vVtxAlign.erase(m_vVtxAlign.begin()+vtxindex);
238  	m_vNmlSrc.erase(m_vNmlSrc.begin()+vtxindex);
239  	m_vNmlTrans.erase(m_vNmlTrans.begin()+vtxindex);
240  	m_vNmlAlign.erase(m_vNmlAlign.begin()+vtxindex);
241 
242 	// decrement each index above vtxindex
243 	polyiter = m_vPolygon.begin();
244 	polyend = m_vPolygon.end();
245 	for (; polyiter != polyend; ++polyiter) {
246 		(*polyiter)->decrement(vtxindex);
247 	}
248 	return true;
249 }
250 
getPolygon(int index)251 Polygon3D * Shape3D::getPolygon(int index) {
252 	if ( index < 0 || index >= (signed)m_vPolygon.size() ) {
253 		return NULL;
254 	}
255 	return m_vPolygon[index];
256 }
257 
getPolygonSize()258 int Shape3D::getPolygonSize() {
259 	return m_vPolygon.size();
260 }
261 
getPolygonIndex(Polygon3D * poly)262 int Shape3D::getPolygonIndex(Polygon3D * poly) {
263 	if (poly == NULL) return -1;
264 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
265 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
266 	for (int a=0; iter != end; iter++, a++) {
267 		if ((*iter) == poly) return a;
268 	}
269 	return -1;
270 }
271 
removePolygon(Polygon3D * poly)272 void Shape3D::removePolygon(Polygon3D * poly) {
273 	if (poly == NULL) return;
274 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
275 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
276 	for (; iter != end; iter++) {
277 		if ((*iter) == poly) {
278 			m_vPolygon.erase(iter);
279 			return;
280 		}
281 	}
282 }
283 
find(float x,float y,float z,float diff)284 int Shape3D::find(float x, float y, float z, float diff) {
285 	vector<Vertex3D>::iterator iter = m_vVtxSrc.begin();
286 	vector<Vertex3D>::iterator end = m_vVtxSrc.end();
287 	for (int a=0; iter != end; iter++, a++) {
288 		if ((*iter).x < x+diff && (*iter).x > x-diff &&
289 				(*iter).y < y+diff && (*iter).y > y-diff &&
290 				(*iter).z < z+diff && (*iter).z > z-diff)
291 			return a;
292 	}
293 	return -1;
294 }
295 
add(Polygon3D * p)296 void Shape3D::add(Polygon3D* p) {
297 	if (p == NULL) return;
298 	m_vPolygon.push_back(p);
299 }
300 
301 /* Sets all polygons to color c. */
setColor(float r,float g,float b,float a)302 void Shape3D::setColor(float r, float g, float b, float a) {
303 	vector<Polygon3D*>::iterator iter = m_vPolygon.begin();
304 	vector<Polygon3D*>::iterator end = m_vPolygon.end();
305 
306 	for ( ; iter != end; iter++) {
307 		(*iter)->setColor(r,g,b,a);
308 	}
309 }
310 
311 /* Counts normals for all vertices in Shape3D. */
countNormals()312 void Shape3D::countNormals() {
313 	vector<Vertex3D>::iterator nmlIter = m_vNmlSrc.begin();
314 	vector<Vertex3D>::iterator nmlEnd = m_vNmlSrc.end();
315 	for (int a=0; nmlIter != nmlEnd; nmlIter++, a++) {
316 		(*nmlIter).x = 0;
317 		(*nmlIter).y = 0;
318 		(*nmlIter).z = 0;
319 		// Get the avrage of all normals in which the vertex resides.
320 		vector<Polygon3D*>::iterator polyIter = m_vPolygon.begin();
321 		vector<Polygon3D*>::iterator polyEnd = m_vPolygon.end();
322 		for (; polyIter != polyEnd; polyIter++) {
323 			if ((*polyIter)->includes(a) >= 0) {
324 				(*nmlIter).x += (*polyIter)->m_nmlSrc.x;
325 				(*nmlIter).y += (*polyIter)->m_nmlSrc.y;
326 				(*nmlIter).z += (*polyIter)->m_nmlSrc.z;
327 			}
328 		}
329 		if ( EM_ZERO((*nmlIter).x)	&&
330 				EM_ZERO((*nmlIter).y) &&
331 				EM_ZERO((*nmlIter).z) ) {
332 			(*nmlIter).y = 1;
333 		}
334 
335 		EMath::normalizeVector((*nmlIter));
336 	}
337 }
338 
getCollisionSize()339 float Shape3D::getCollisionSize() {
340 	float size = 0;
341 
342 	vector<Vertex3D>::iterator iter = m_vVtxSrc.begin();
343 	vector<Vertex3D>::iterator end = m_vVtxSrc.end();
344 	for ( ; iter != end; iter++) {
345 		if (EM_ABS((*iter).x) > size) size = EM_ABS((*iter).x);
346 		if (EM_ABS((*iter).y) > size) size = EM_ABS((*iter).y);
347 		if (EM_ABS((*iter).z) > size) size = EM_ABS((*iter).z);
348 	}
349 
350 	return size;
351 }
352