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