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