d69ecc4e425da9d835aae17a2d699fd0591f95b9
[scilab.git] / scilab / modules / graphic_objects / src / cpp / Fac3DDecomposer.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - DIGITEO - Manuel Juliachs
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "DecompositionUtils.hxx"
14 #include "ColorComputer.hxx"
15 #include "Fac3DColorComputer.hxx"
16 #include "Fac3DDecomposer.hxx"
17
18 extern "C"
19 {
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "getGraphicObjectProperty.h"
24 #include "graphicObjectProperties.h"
25 }
26
27 int Fac3DDecomposer::getDataSize(char* id)
28 {
29     int numVerticesPerGon = 0;
30     int* piNumVerticesPerGon = &numVerticesPerGon;
31     int numGons = 0;
32     int* piNumGons = &numGons;
33
34     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
35     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
36
37     return numVerticesPerGon*numGons;
38 }
39
40 void Fac3DDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
41 {
42     double* x = NULL;
43     double* y = NULL;
44     double* z = NULL;
45
46     int i = 0;
47
48     int numVerticesPerGon = 0;
49     int* piNumVerticesPerGon = &numVerticesPerGon;
50     int numGons = 0;
51     int* piNumGons = &numGons;
52
53     int bufferOffset = 0;
54
55     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
56     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
57
58     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_int, (void**) &x);
59     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_int, (void**) &y);
60     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_int, (void**) &z);
61
62
63     for (i = 0; i < numVerticesPerGon*numGons; i++)
64     {
65         if (coordinateMask & 0x1)
66         {
67             double xi = x[i];
68             if (logMask & 0x1)
69             {
70                 xi = DecompositionUtils::getLog10Value(x[i]);
71             }
72             buffer[bufferOffset] = (float)(xi * scale[0] + translation[0]);
73         }
74
75         if (coordinateMask & 0x2)
76         {
77             double yi = y[i];
78             if (logMask & 0x2)
79             {
80                 yi = DecompositionUtils::getLog10Value(y[i]);
81             }
82             buffer[bufferOffset + 1] = (float)(yi * scale[1] + translation[1]);
83         }
84
85         if (coordinateMask & 0x4)
86         {
87             double zi = z[i];
88             if (logMask & 0x4)
89             {
90                 zi = DecompositionUtils::getLog10Value(z[i]);
91             }
92             buffer[bufferOffset + 2] = (float)(zi * scale[2] + translation[2]);
93         }
94
95         if (elementsSize == 4 && (coordinateMask & 0x8))
96         {
97             buffer[bufferOffset + 3] = 1.0;
98         }
99
100         bufferOffset += 4;
101     }
102
103 }
104
105 void Fac3DDecomposer::fillTextureCoordinates(char* id, float* buffer, int bufferLength)
106 {
107     char* parentFigure = NULL;
108     char* parent = NULL;
109
110     double* colors = NULL;
111     double* colormap = NULL;
112     double* z = NULL;
113
114     double color = 0.;
115
116     int numVerticesPerGon = 0;
117     int* piNumVerticesPerGon = &numVerticesPerGon;
118     int numGons = 0;
119     int* piNumGons = &numGons;
120     int numColors = 0;
121     int* piNumColors = &numColors;
122
123     int colormapSize = 0;
124     int* piColormapSize = &colormapSize;
125
126     int colorFlag = 0;
127     int* piColorFlag = &colorFlag;
128
129     int dataMapping =  0;
130     int* piDataMapping = &dataMapping;
131
132     int perVertex = 0;
133
134
135     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
136     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
137
138     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_COLORS__, jni_int, (void**) &piNumColors);
139     getGraphicObjectProperty(id, __GO_DATA_MODEL_COLORS__, jni_double_vector, (void**) &colors);
140
141     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
142
143     /* Temporary: to avoid getting a null parent_figure property when the object is built */
144     if (strcmp(parent, "") == 0)
145     {
146         return;
147     }
148
149     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
150
151     if (parentFigure == NULL)
152     {
153         return;
154     }
155
156     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
157     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
158
159     getGraphicObjectProperty(id, __GO_COLOR_FLAG__, jni_int, (void**) &piColorFlag);
160
161     getGraphicObjectProperty(id, __GO_DATA_MAPPING__, jni_int, (void**) &piDataMapping);
162
163     /* Do not fill */
164     if (colorFlag == 0)
165     {
166         return;
167     }
168
169     if (numColors == numGons*numVerticesPerGon)
170     {
171         perVertex = 1;
172     }
173     else if (numColors == numGons)
174     {
175         perVertex = 0;
176     }
177
178
179     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_int, (void**) &z);
180
181     if (colorFlag == 1)
182     {
183         fillNormalizedZColorsTextureCoordinates(buffer, bufferLength, colormap, colormapSize, z, numGons, numVerticesPerGon);
184     }
185     else if (colorFlag > 1 && numColors == 0)
186     {
187         /*
188          * The color buffer must be filled with the color_mode value.
189          * To do: correctly take into account Nan and infinite values.
190          */
191         int colorMode = 0;
192         int* piColorMode = &colorMode;
193
194         getGraphicObjectProperty(id, __GO_COLOR_MODE__, jni_int, (void**) &piColorMode);
195
196         color = (double) colorMode;
197         color = DecompositionUtils::getAbsoluteValue(color);
198
199         fillConstantColorsTextureCoordinates(buffer, bufferLength, colormap, colormapSize,
200                                              color, numGons, numVerticesPerGon);
201     }
202     else
203     {
204         fillDataColorsTextureCoordinates(buffer, bufferLength, colormap, colormapSize,
205                                          colors, colorFlag, perVertex, dataMapping, numGons, numVerticesPerGon);
206     }
207
208 }
209
210 void Fac3DDecomposer::fillNormalizedZColorsTextureCoordinates(float* buffer, int bufferLength, double* colormap, int colormapSize,
211                                                               double* z, int numGons, int numVerticesPerGon)
212 {
213     double zavg = 0.;
214     double zMin = 0.;
215     double zMax = 0.;
216     double zRange = 0.;
217     double minDoubleValue = 0.;
218     float index = 0.;
219
220     int i = 0;
221     int j = 0;
222     int bufferOffset = 0;
223
224     computeMinMaxValues(z, numGons*numVerticesPerGon, numGons, numVerticesPerGon, ALL_VALUES, &zMin, &zMax);
225
226     minDoubleValue = DecompositionUtils::getMinDoubleValue();
227
228     /* To be verified */
229     if ((zMax - zMin) < minDoubleValue)
230     {
231         zRange = 1.0;
232     }
233     else
234     {
235         zRange = zMax - zMin;
236     }
237
238     for (i = 0; i < numGons; i++)
239     {
240         /* Per-face average */
241         zavg = computeAverageValue(&z[i*numVerticesPerGon], numVerticesPerGon);
242         index = (float)((ColorComputer::getIndex(zavg, zMin, zRange, Z_COLOR_OFFSET, 0, colormapSize - 1) + 2.0 + COLOR_TEXTURE_OFFSET) / (float) (colormapSize + 2));
243
244         for (j = 0; j < numVerticesPerGon; j++)
245         {
246             buffer[bufferOffset++] = index;
247             buffer[bufferOffset++] = 0;
248             buffer[bufferOffset++] = 0;
249             buffer[bufferOffset++] = 1.0;
250         }
251     }
252
253 }
254
255 void Fac3DDecomposer::fillConstantColorsTextureCoordinates(float* buffer, int bufferLength, double* colormap, int colormapSize,
256                                                            double colorValue, int numGons, int numVerticesPerGon)
257 {
258     int bufferOffset = 0;
259
260     double index = (ColorComputer::getClampedDirectIndex(colorValue - 1.0, colormapSize) + 2.0 + COLOR_TEXTURE_OFFSET) / (float) (colormapSize + 2);
261
262     for (int i = 0; i < numGons*numVerticesPerGon; i++)
263     {
264         buffer[bufferOffset++] = (float)index;
265         buffer[bufferOffset++] = 0;
266         buffer[bufferOffset++] = 0;
267         buffer[bufferOffset++] = 1.0;
268     }
269
270 }
271
272 void Fac3DDecomposer::fillDataColorsTextureCoordinates(float* buffer, int bufferLength, double* colormap, int colormapSize,
273                                                        double* colors, int colorFlag, int perVertex, int dataMapping, int numGons, int numVerticesPerGon)
274 {
275     double colMin = 0.;
276     double colRange = 0.;
277     double color = 0.;
278     double colorTextureOffset = 0.;
279     double index = 0.;
280
281     int bufferOffset = 0;
282
283     int numColors = 0;
284
285     Fac3DColorComputer colorComputer;
286
287     if (perVertex)
288     {
289         numColors = numGons*numVerticesPerGon;
290     }
291     else
292     {
293         numColors = numGons;
294     }
295
296     colorComputer = Fac3DColorComputer(colors, numColors, colorFlag, dataMapping, numGons, numVerticesPerGon);
297
298     /* 0: colors are scaled */
299     if (dataMapping == 0)
300     {
301         colorComputer.getColorRangeValue(&colMin, &colRange);
302     }
303
304     /*
305      * The color texture offset value is used to center color sub-intervals
306      * on integer index values when interpolated shading is used or to be sure
307      * to fetch the correct color value when flat shading is used.
308      */
309     colorTextureOffset = COLOR_TEXTURE_OFFSET;
310
311     for (int i = 0; i < numGons; i++)
312     {
313         for (int j = 0; j < numVerticesPerGon; j++)
314         {
315             color = colorComputer.getOutputFacetColor(i, j);
316
317             if (dataMapping == 1)
318             {
319                 color = DecompositionUtils::getAbsoluteValue(color);
320                 index = ColorComputer::getClampedDirectIndex(color - 1.0 , colormapSize);
321             }
322             else if (dataMapping == 0)
323             {
324                 index = ColorComputer::getIndex(color, colMin, colRange, COLOR_OFFSET, 0, colormapSize-1);
325             }
326
327             /* The offset corresponding to the black and white colors must added to the index and the colormap size. */
328             buffer[bufferOffset++] = (float) ((index + colorTextureOffset + 2.0) / (double) (colormapSize + 2));
329             buffer[bufferOffset++] = 0;
330             buffer[bufferOffset++] = 0;
331             buffer[bufferOffset++] = 1.0;
332         }
333     }
334 }
335
336 double Fac3DDecomposer::computeAverageValue(double* values, int numVertices)
337 {
338     double averageValue = 0.0;
339
340     for (int i = 0; i < numVertices; i++)
341     {
342         averageValue += values[i];
343     }
344
345     averageValue /= (double) numVertices;
346
347     return averageValue;
348 }
349
350 void Fac3DDecomposer::computeMinMaxValues(double* values, int numValues, int numGons, int numVerticesPerGon, int minMaxComputation,
351                                           double* valueMin, double* valueMax)
352 {
353     double maxDouble = DecompositionUtils::getMaxDoubleValue();
354     double tmpValueMin = maxDouble;
355     double tmpValueMax = -maxDouble;
356     double value = 0.;
357
358     int numIterations = 0;
359
360     if (minMaxComputation != ALL_VALUES)
361     {
362         numIterations = numGons;
363     }
364     else
365     {
366         numIterations = numValues;
367     }
368
369     for (int i = 0; i < numIterations; i++)
370     {
371         if (minMaxComputation == FIRST_VERTEX_VALUE)
372         {
373             value = values[i*numVerticesPerGon];
374         }
375         else if (minMaxComputation == FACE_AVERAGE)
376         {
377             value = computeAverageValue(&values[i*numVerticesPerGon], numVerticesPerGon);
378         }
379         else
380         {
381             value = values[i];
382         }
383
384         if (DecompositionUtils::isValid(value))
385         {
386             if (value < tmpValueMin)
387             {
388                 tmpValueMin = value;
389             }
390
391             if (value > tmpValueMax)
392             {
393                 tmpValueMax = value;
394             }
395         }
396     }
397
398     *valueMin = tmpValueMin;
399     *valueMax = tmpValueMax;
400 }
401
402 int Fac3DDecomposer::getIndicesSize(char* id)
403 {
404     int numVerticesPerGon = 0;
405     int* piNumVerticesPerGon = &numVerticesPerGon;
406     int numGons = 0;
407     int* piNumGons = &numGons;
408
409     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
410     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
411
412     if (numVerticesPerGon < 2)
413     {
414         return 0;
415     }
416
417     return 3*(numVerticesPerGon-2)*numGons;
418 }
419
420 /*
421  * To do: use a polygon triangulation algorithm, as the fan decomposition used may produce
422  * overlapping triangles for non-convex polygons.
423  */
424 int Fac3DDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
425 {
426     double* x = NULL;
427     double* y = NULL;
428     double* z = NULL;
429
430     double xc = 0.;
431     double yc = 0.;
432     double zc = 0.;
433
434     double* colors = NULL;
435
436     int numVerticesPerGon = 0;
437     int* piNumVerticesPerGon = &numVerticesPerGon;
438     int numGons = 0;
439     int* piNumGons = &numGons;
440
441     int numColors = 0;
442     int* piNumColors = &numColors;
443
444     int colorFlag = 0;
445     int* piColorFlag = &colorFlag;
446
447     int dataMapping =  0;
448     int* piDataMapping = &dataMapping;
449
450     int bufferOffset = 0;
451     int vertexOffset = 0;
452
453     Fac3DColorComputer colorComputer;
454
455     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
456     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
457
458     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_COLORS__, jni_int, (void**) &piNumColors);
459     getGraphicObjectProperty(id, __GO_DATA_MODEL_COLORS__, jni_double_vector, (void**) &colors);
460
461     getGraphicObjectProperty(id, __GO_COLOR_FLAG__, jni_int, (void**) &piColorFlag);
462
463     getGraphicObjectProperty(id, __GO_DATA_MAPPING__, jni_int, (void**) &piDataMapping);
464
465     /* At least 3 vertices per N-gon are required to output triangles. */
466     if (numVerticesPerGon < 3)
467     {
468         return 0;
469     }
470
471     colorComputer = Fac3DColorComputer(colors, numColors, colorFlag, dataMapping, numGons, numVerticesPerGon);
472
473     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
474     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
475     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
476
477     for (int i = 0; i < numGons; i++)
478     {
479         int isValid = 1;
480
481         for (int j = 0; j < numVerticesPerGon; j++)
482         {
483             xc = x[vertexOffset+j];
484             yc = y[vertexOffset+j];
485             zc = z[vertexOffset+j];
486
487             if (!DecompositionUtils::isValid(xc, yc, zc) || !DecompositionUtils::isLogValid(xc, yc, zc, logMask))
488             {
489                 isValid = 0;
490                 break;
491             }
492         }
493
494         if (isValid == 0 || colorComputer.isFacetColorValid(i) == 0)
495         {
496             vertexOffset += numVerticesPerGon;
497             continue;
498         }
499
500         /* Performs a fan decomposition, vertices are ordered counter-clockwise. */
501         for (int j = 0; j < numVerticesPerGon-2; j++)
502         {
503             buffer[bufferOffset] = vertexOffset;
504             buffer[bufferOffset +1] = vertexOffset + j+2;
505             buffer[bufferOffset +2] = vertexOffset + j+1;
506
507             bufferOffset += 3;
508         }
509
510         vertexOffset += numVerticesPerGon;
511     }
512
513     return bufferOffset;
514 }
515
516 int Fac3DDecomposer::getWireIndicesSize(char* id)
517 {
518     int numVerticesPerGon = 0;
519     int* piNumVerticesPerGon = &numVerticesPerGon;
520     int numGons = 0;
521     int* piNumGons = &numGons;
522
523     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
524     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
525
526     return 2*numVerticesPerGon*numGons;
527 }
528
529 int Fac3DDecomposer::fillWireIndices(char* id, int* buffer, int bufferLength, int logMask)
530 {
531     double* x = NULL;
532     double* y = NULL;
533     double* z = NULL;
534
535     double xc = 0.;
536     double yc = 0.;
537     double zc = 0.;
538
539     int numVerticesPerGon = 0;
540     int* piNumVerticesPerGon = &numVerticesPerGon;
541     int numGons = 0;
542     int* piNumGons = &numGons;
543
544     int bufferOffset = 0;
545     int vertexOffset = 0;
546
547     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES_PER_GON__, jni_int, (void**) &piNumVerticesPerGon);
548     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_GONS__, jni_int, (void**) &piNumGons);
549
550     /* At least 2 vertices per N-gon are required to output segments. */
551     if (numVerticesPerGon < 2)
552     {
553         return 0;
554     }
555
556     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
557     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
558     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
559
560     for (int i = 0; i < numGons; i++)
561     {
562         int isValid = 1;
563
564         for (int j = 0; j < numVerticesPerGon; j++)
565         {
566             xc = x[vertexOffset+j];
567             yc = y[vertexOffset+j];
568             zc = z[vertexOffset+j];
569
570             if (!DecompositionUtils::isValid(xc, yc, zc) || !DecompositionUtils::isLogValid(xc, yc, zc, logMask))
571             {
572                 isValid = 0;
573                 break;
574             }
575         }
576
577         if (isValid == 0)
578         {
579             vertexOffset += numVerticesPerGon;
580             continue;
581         }
582
583         for (int j = 0; j < numVerticesPerGon; j++)
584         {
585             buffer[bufferOffset] = vertexOffset + j;
586             buffer[bufferOffset+1] = vertexOffset + (j+1) % numVerticesPerGon;
587
588             bufferOffset += 2;
589         }
590
591         vertexOffset += numVerticesPerGon;
592     }
593
594     return bufferOffset;
595 }
596