1 // libSNL - Simple Nurbs Library
2 // Copyright 2003 Scott A.E. Lanham, Australia.
3 // --------------------------------------------
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
13 //
14 // You should have received a copy of the GNU Library General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 // *** 2D Vertex Net ***
19
20 // Natural orientation of the network is:
21 //
22 // Maximum V
23 // |
24 // |
25 // |
26 // |
27 // 0 ------- Maximum U
28 //
29 // You are looking at the front face. Unless you are inside the monitor ;-)
30
31 #include "snlVertexNet.h"
32
snlVertexNet()33 snlVertexNet::snlVertexNet()
34 {
35 vertex_net = 0;
36
37 size_u = 0;
38 size_v = 0;
39 }
40
~snlVertexNet()41 snlVertexNet::~snlVertexNet()
42 {
43 if ( vertex_net ) delete[] vertex_net;
44 }
45
snlVertexNet(const snlVertexNet & copyFrom)46 snlVertexNet::snlVertexNet ( const snlVertexNet& copyFrom )
47 {
48 // Copy constructor.
49 // -----------------
50
51 int arraySize = copyFrom.size_u * copyFrom.size_v;
52
53 vertex_net = new snlVertex [ arraySize ];
54
55 for ( int index = 0; index < arraySize; index ++ )
56 vertex_net [ index ] = copyFrom.vertex_net [ index ];
57 }
58
vertexNet(const snlCtrlPoint * ctrlPts,int sizeU,int sizeV)59 void snlVertexNet::vertexNet ( const snlCtrlPoint* ctrlPts, int sizeU, int sizeV )
60 {
61 // Generate vertex net based on control point net.
62 // -----------------------------------------------
63 // ctrlPts: Array of control points to copy.
64 // sizeU: Size of array in first dimension.
65 // sizeV: Size of array in second dimension.
66
67 if ( vertex_net ) delete[] vertex_net;
68
69 int numPts = sizeU * sizeV;
70
71 vertex_net = new snlVertex [ numPts ];
72
73 size_u = sizeU;
74 size_v = sizeV;
75
76 // Translate control points into vertexs.
77
78 for ( int index = 0; index < numPts; index ++ )
79 {
80 vertex_net [ index ] = ctrlPts [ index ];
81 vertex_net [ index ].normalise();
82 }
83
84 calcNormals();
85 }
86
vertexNet(const snlCtrlPoint * ctrlPts,int numPts)87 void snlVertexNet::vertexNet ( const snlCtrlPoint* ctrlPts, int numPts )
88 {
89 // Generate vertex net based on 1-D control point array.
90 // -----------------------------------------------------
91 // Notes: Normals aren't calculated for a curve.
92
93 if ( vertex_net ) delete[] vertex_net;
94
95 vertex_net = new snlVertex [ numPts ];
96
97 size_u = 1;
98 size_v = numPts;
99
100 // Translate control points into vertexs.
101
102 for ( int index = 0; index < numPts; index ++ )
103 {
104 vertex_net [ index ] = ctrlPts [ index ];
105 vertex_net [ index ].normalise();
106 ( vertex_net [ index ].normal() ).zero();
107 }
108 }
109
vertexNet(const snlPoint * pts,int sizeU,int sizeV)110 void snlVertexNet::vertexNet ( const snlPoint* pts, int sizeU, int sizeV )
111 {
112 // Generate vertex net based on point net.
113 // ---------------------------------------
114 // ctrlPts: Array of control points to copy.
115 // sizeU: Size of array in first dimension.
116 // sizeV: Size of array in second dimension.
117
118 if ( vertex_net ) delete[] vertex_net;
119
120 int numPts = sizeU * sizeV;
121
122 vertex_net = new snlVertex [ numPts ];
123
124 size_u = sizeU;
125 size_v = sizeV;
126
127 // Translate control points into vertexs.
128
129 for ( int index = 0; index < numPts; index ++ )
130 {
131 vertex_net [ index ] = pts [ index ];
132 vertex_net [ index ].normalise();
133 }
134
135 calcNormals();
136 }
137
vertexNet(const snlPoint * pts,int numPts)138 void snlVertexNet::vertexNet ( const snlPoint* pts, int numPts )
139 {
140 // Generate vertex net based on 1-D point array.
141 // ---------------------------------------------
142 // Notes: Normals aren't calculated for a curve.
143
144 if ( vertex_net ) delete[] vertex_net;
145
146 vertex_net = new snlVertex [ numPts ];
147
148 size_u = 1;
149 size_v = numPts;
150
151 // Translate control points into vertexs.
152
153 for ( int index = 0; index < numPts; index ++ )
154 {
155 vertex_net [ index ] = pts [ index ];
156 vertex_net [ index ].normalise();
157 ( vertex_net [ index ].normal() ).zero();
158 }
159 }
160
appendRow(const snlCtrlPoint * ctrlPts)161 void snlVertexNet::appendRow ( const snlCtrlPoint* ctrlPts )
162 {
163 // Append row of points to end of net.
164 // -----------------------------------
165
166 if ( size_u < 1 ) return; // Can't append to empty array.
167
168 int numPts = size_u * size_v;
169
170 snlVertex* newVNet = new snlVertex [ numPts + size_v ];
171
172 int index;
173
174 for ( index = 0; index < numPts; index ++ )
175 newVNet [ index ] = vertex_net [ index ];
176
177 for ( index = 0; index < size_v; index ++ )
178 {
179 newVNet [ index + numPts ] = ctrlPts [ index ];
180 newVNet [ index + numPts ].normalise();
181 }
182
183 // Install new array.
184
185 size_u ++;
186
187 if ( vertex_net ) delete[] vertex_net;
188
189 vertex_net = newVNet;
190
191 calcNormals();
192 }
193
vertex(int index)194 snlVertex* snlVertexNet::vertex ( int index )
195 {
196 // Return reference to vertex at index.
197 // ------------------------------------
198
199 return vertex_net + index;
200 }
201
vertex(int U,int V)202 snlVertex* snlVertexNet::vertex ( int U, int V )
203 {
204 // Return vertex at U,V coordinates.
205 // ---------------------------------
206
207 return vertex_net + ( U * size_v + V );
208 }
209
vertexes()210 snlVertex* snlVertexNet::vertexes()
211 {
212 // Return pointer to vertex array.
213 // -------------------------------
214
215 return vertex_net;
216 }
217
size() const218 int snlVertexNet::size() const
219 {
220 // Return total number of vertexes.
221 // --------------------------------
222
223 return size_u * size_v;
224 }
225
sizeU() const226 int snlVertexNet::sizeU() const
227 {
228 return size_u;
229 }
230
sizeV() const231 int snlVertexNet::sizeV() const
232 {
233 return size_v;
234 }
235
calcNormals()236 void snlVertexNet::calcNormals()
237 {
238 // Calculate normals based on the vertex network.
239 // ----------------------------------------------
240 //
241 // Notes: maxV
242 // |
243 // minU --0-- maxU
244 // |
245 // minV
246
247
248 snlVector maxU;
249 bool useMaxU;
250
251 snlVector minU;
252 bool useMinU;
253
254 snlVector maxV;
255 bool useMaxV;
256
257 snlVector minV;
258 bool useMinV;
259
260 for ( int indexU = 0; indexU < size_u; indexU ++ )
261 {
262 for ( int indexV = 0; indexV < size_v; indexV ++ )
263 {
264 int baseIndex = indexU * size_v + indexV;
265
266 // U direction vectors.
267
268 if ( indexU < size_u - 1 )
269 {
270 // MaxU can be calculated.
271
272 maxU.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex + size_v ] );
273 useMaxU = true;
274 }
275 else
276 useMaxU = false;
277
278 if ( indexU > 0 )
279 {
280 // MinU can be calculated.
281
282 minU.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex - size_v ] );
283 useMinU = true;
284 }
285 else
286 useMinU = false;
287
288 // V direction vectors.
289
290 if ( indexV < size_v - 1 )
291 {
292 // Calculate maxV.
293 maxV.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex + 1 ] );
294 useMaxV = true;
295 }
296 else
297 useMaxV = false;
298
299 if ( indexV > 0 )
300 {
301 minV.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex - 1 ] );
302 useMinV = true;
303 }
304 else
305 useMinV = false;
306
307 // Calculate normals by combining normals from all combinations of
308 // available vectors.
309
310 snlVector tmpNormal;
311 snlVector finalNormal;
312
313 finalNormal.zero();
314
315 if ( useMaxV && useMinU )
316 {
317 tmpNormal.crossProduct ( maxV, minU );
318 finalNormal += tmpNormal;
319
320 // Process diagonals.
321
322 snlVector diag;
323 diag.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex + 1 - size_v ] );
324
325 tmpNormal.crossProduct ( maxV, diag );
326 finalNormal += tmpNormal;
327
328 tmpNormal.crossProduct ( diag, minU );
329 finalNormal += tmpNormal;
330 }
331
332 if ( useMinU && useMinV )
333 {
334 tmpNormal.crossProduct ( minU, minV );
335 finalNormal += tmpNormal;
336
337 // Process diagonals.
338
339 snlVector diag;
340 diag.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex - 1 - size_v ] );
341
342 tmpNormal.crossProduct ( minU, diag );
343 finalNormal += tmpNormal;
344
345 tmpNormal.crossProduct ( diag, minV );
346 finalNormal += tmpNormal;
347 }
348
349 if ( useMinV && useMaxU )
350 {
351 tmpNormal.crossProduct ( minV, maxU );
352 finalNormal += tmpNormal;
353
354 // Process diagonals.
355
356 snlVector diag;
357 diag.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex - 1 + size_v ] );
358
359 tmpNormal.crossProduct ( minV, diag );
360 finalNormal += tmpNormal;
361
362 tmpNormal.crossProduct ( diag, maxU );
363 finalNormal += tmpNormal;
364 }
365
366 if ( useMaxU && useMaxV )
367 {
368 tmpNormal.crossProduct ( maxU, maxV );
369 finalNormal += tmpNormal;
370
371 // Process diagonals.
372
373 snlVector diag;
374 diag.calc ( vertex_net [ baseIndex ], vertex_net [ baseIndex + 1 + size_v ] );
375
376 tmpNormal.crossProduct ( maxU, diag );
377 finalNormal += tmpNormal;
378
379 tmpNormal.crossProduct ( diag, maxV );
380 finalNormal += tmpNormal;
381 }
382
383 // Set vertex's normal.
384
385 finalNormal.unitise();
386
387 vertex_net [ baseIndex ].normal ( finalNormal );
388 }
389 }
390 }
391
392
393
394