Coverage Report

Created: 2025-11-11 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl
Line
Count
Source
1
/*
2
Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
3
4
Permission is hereby granted, free of charge, to any person obtaining a copy
5
of this software and associated documentation files (the "Software"), to deal
6
in the Software without restriction, including without limitation the rights
7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in
12
all copies or substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
THE SOFTWARE.
21
*/
22
23
#pragma once
24
#ifndef O3DGC_SC3DMC_ENCODER_INL
25
#define O3DGC_SC3DMC_ENCODER_INL
26
27
#include "o3dgcArithmeticCodec.h"
28
#include "o3dgcTimer.h"
29
#include "o3dgcVector.h"
30
#include "o3dgcBinaryStream.h"
31
#include "o3dgcCommon.h"
32
33
//#define DEBUG_VERBOSE
34
35
#ifdef _MSC_VER
36
#    pragma warning(push)
37
#    pragma warning(disable : 4456)
38
#endif // _MSC_VER
39
40
namespace o3dgc
41
{
42
#ifdef DEBUG_VERBOSE
43
        FILE * g_fileDebugSC3DMCEnc = NULL;
44
#endif //DEBUG_VERBOSE
45
46
    template <class T>
47
    O3DGCErrorCode SC3DMCEncoder<T>::Encode(const SC3DMCEncodeParams & params, 
48
                                            const IndexedFaceSet<T> & ifs, 
49
                                            BinaryStream & bstream)
50
0
    {
51
        // Encode header
52
0
        unsigned long start = bstream.GetSize();
53
0
        EncodeHeader(params, ifs, bstream);
54
        // Encode payload
55
0
        EncodePayload(params, ifs, bstream);
56
0
        bstream.WriteUInt32(m_posSize, bstream.GetSize() - start, m_streamType);
57
0
        return O3DGC_OK;
58
0
    }
59
    template <class T>
60
    O3DGCErrorCode SC3DMCEncoder<T>::EncodeHeader(const SC3DMCEncodeParams & params, 
61
                                               const IndexedFaceSet<T> & ifs, 
62
                                               BinaryStream & bstream)
63
0
    {
64
0
        m_streamType = params.GetStreamType();
65
0
        bstream.WriteUInt32(O3DGC_SC3DMC_START_CODE, m_streamType);
66
0
        m_posSize = bstream.GetSize();
67
0
        bstream.WriteUInt32(0, m_streamType); // to be filled later
68
69
0
        bstream.WriteUChar(O3DGC_SC3DMC_ENCODE_MODE_TFAN, m_streamType);
70
0
        bstream.WriteFloat32((float)ifs.GetCreaseAngle(), m_streamType);
71
          
72
0
        unsigned char mask = 0;
73
0
        bool markerBit0 = false;
74
0
        bool markerBit1 = false;
75
0
        bool markerBit2 = false;
76
0
        bool markerBit3 = false;
77
78
0
        mask += (ifs.GetCCW()                  );
79
0
        mask += (ifs.GetSolid()            << 1);
80
0
        mask += (ifs.GetConvex()           << 2);
81
0
        mask += (ifs.GetIsTriangularMesh() << 3);
82
0
        mask += (markerBit0                << 4);
83
0
        mask += (markerBit1                << 5);
84
0
        mask += (markerBit2                << 6);
85
0
        mask += (markerBit3                << 7);
86
87
0
        bstream.WriteUChar(mask, m_streamType);
88
89
0
        bstream.WriteUInt32(ifs.GetNCoord(), m_streamType);
90
0
        bstream.WriteUInt32(ifs.GetNNormal(), m_streamType);
91
0
        bstream.WriteUInt32(ifs.GetNumFloatAttributes(), m_streamType);
92
0
        bstream.WriteUInt32(ifs.GetNumIntAttributes(), m_streamType);
93
94
0
        if (ifs.GetNCoord() > 0)
95
0
        {
96
0
            bstream.WriteUInt32(ifs.GetNCoordIndex(), m_streamType);
97
0
            for(int j=0 ; j<3 ; ++j)
98
0
            {
99
0
                bstream.WriteFloat32((float) ifs.GetCoordMin(j), m_streamType);
100
0
                bstream.WriteFloat32((float) ifs.GetCoordMax(j), m_streamType);
101
0
            }            
102
0
            bstream.WriteUChar((unsigned char) params.GetCoordQuantBits(), m_streamType);
103
0
        }
104
0
        if (ifs.GetNNormal() > 0)
105
0
        {
106
0
            bstream.WriteUInt32(0, m_streamType);
107
0
             for(int j=0 ; j<3 ; ++j)
108
0
            {
109
0
                bstream.WriteFloat32((float) ifs.GetNormalMin(j), m_streamType);
110
0
                bstream.WriteFloat32((float) ifs.GetNormalMax(j), m_streamType);
111
0
            }
112
0
            bstream.WriteUChar(true, m_streamType); //(unsigned char) ifs.GetNormalPerVertex()
113
0
            bstream.WriteUChar((unsigned char) params.GetNormalQuantBits(), m_streamType);
114
0
        }
115
0
        for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
116
0
        {
117
0
            bstream.WriteUInt32(ifs.GetNFloatAttribute(a), m_streamType);
118
0
            if (ifs.GetNFloatAttribute(a) > 0)
119
0
            {
120
0
                assert(ifs.GetFloatAttributeDim(a) < (unsigned long) O3DGC_MAX_UCHAR8);
121
0
                bstream.WriteUInt32(0, m_streamType);
122
0
                unsigned char d = (unsigned char) ifs.GetFloatAttributeDim(a);
123
0
                bstream.WriteUChar(d, m_streamType);
124
0
                for(unsigned char j = 0 ; j < d ; ++j)
125
0
                {
126
0
                    bstream.WriteFloat32((float) ifs.GetFloatAttributeMin(a, j), m_streamType);
127
0
                    bstream.WriteFloat32((float) ifs.GetFloatAttributeMax(a, j), m_streamType);
128
0
                }
129
0
                bstream.WriteUChar(true, m_streamType); //(unsigned char) ifs.GetFloatAttributePerVertex(a)
130
0
                bstream.WriteUChar((unsigned char) ifs.GetFloatAttributeType(a), m_streamType);
131
0
                bstream.WriteUChar((unsigned char) params.GetFloatAttributeQuantBits(a), m_streamType);
132
0
            }
133
0
        }
134
0
        for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
135
0
        {
136
0
            bstream.WriteUInt32(ifs.GetNIntAttribute(a), m_streamType);
137
0
            if (ifs.GetNIntAttribute(a) > 0)
138
0
            {
139
0
                assert(ifs.GetFloatAttributeDim(a) < (unsigned long) O3DGC_MAX_UCHAR8);
140
0
                bstream.WriteUInt32(0, m_streamType);
141
0
                bstream.WriteUChar((unsigned char) ifs.GetIntAttributeDim(a), m_streamType);
142
0
                bstream.WriteUChar(true, m_streamType); // (unsigned char) ifs.GetIntAttributePerVertex(a)
143
0
                bstream.WriteUChar((unsigned char) ifs.GetIntAttributeType(a), m_streamType);
144
0
            }
145
0
        }    
146
0
        return O3DGC_OK;
147
0
    }
148
    template <class T>
149
    O3DGCErrorCode SC3DMCEncoder<T>::QuantizeFloatArray(const Real * const floatArray, 
150
                                                   unsigned long numFloatArray,
151
                                                   unsigned long dimFloatArray,
152
                                                   unsigned long stride,
153
                                                   const Real * const minFloatArray,
154
                                                   const Real * const maxFloatArray,
155
                                                   unsigned long nQBits)
156
0
    {
157
0
        const unsigned long size = numFloatArray * dimFloatArray;
158
0
        Real delta[O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
159
0
        Real r;
160
0
        for(unsigned long d = 0; d < dimFloatArray; d++)
161
0
        {
162
0
            r = maxFloatArray[d] - minFloatArray[d];
163
0
            if (r > 0.0f)
164
0
            {
165
0
                delta[d] = (float)((1 << nQBits) - 1) / r;
166
0
            }
167
0
            else
168
0
            {
169
0
                delta[d] = 1.0f;
170
0
            }
171
0
        }        
172
0
        if (m_quantFloatArraySize < size)
173
0
        {
174
0
            delete [] m_quantFloatArray;
175
0
            m_quantFloatArraySize = size;
176
0
            m_quantFloatArray     = new long [size];
177
0
        }                                  
178
0
        for(unsigned long v = 0; v < numFloatArray; ++v)
179
0
        {
180
0
            for(unsigned long d = 0; d < dimFloatArray; ++d)
181
0
            {
182
0
                m_quantFloatArray[v * stride + d] = (long)((floatArray[v * stride + d]-minFloatArray[d]) * delta[d] + 0.5f);
183
0
            }
184
0
        }
185
0
        return O3DGC_OK;
186
0
    }
187
    template <class T>
188
    O3DGCErrorCode SC3DMCEncoder<T>::EncodeFloatArray(const Real * const floatArray, 
189
                                                      unsigned long numFloatArray,
190
                                                      unsigned long dimFloatArray,
191
                                                      unsigned long stride,
192
                                                      const Real * const minFloatArray,
193
                                                      const Real * const maxFloatArray,
194
                                                      unsigned long nQBits,
195
                                                      const IndexedFaceSet<T> & ifs,
196
                                                      O3DGCSC3DMCPredictionMode predMode,
197
                                                      BinaryStream & bstream)
198
0
    {
199
0
        assert(dimFloatArray <  O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
200
0
        long predResidual, v, uPredResidual;
201
0
        unsigned long nPred;
202
0
        Arithmetic_Codec ace;
203
0
        Static_Bit_Model bModel0;
204
0
        Adaptive_Bit_Model bModel1;
205
206
0
        const AdjacencyInfo & v2T         = m_triangleListEncoder.GetVertexToTriangle();
207
0
        const long * const    vmap        = m_triangleListEncoder.GetVMap();
208
0
        const long * const    invVMap     = m_triangleListEncoder.GetInvVMap();
209
0
        const T * const       triangles   = ifs.GetCoordIndex();
210
0
        const long            nvert       = (long) numFloatArray;
211
0
        unsigned long         start       = bstream.GetSize();
212
0
        unsigned char         mask        = predMode & 7;
213
0
        const unsigned long   M           = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS - 1;
214
0
        unsigned long         nSymbols    = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS;
215
0
        unsigned long         nPredictors = O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS;
216
        
217
218
0
        Adaptive_Data_Model mModelValues(M+2);
219
0
        Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
220
221
0
        memset(m_freqSymbols, 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS);
222
0
        memset(m_freqPreds  , 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS);
223
0
        if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
224
0
        {
225
0
            mask += (O3DGC_SC3DMC_BINARIZATION_ASCII & 7)<<4;
226
0
            m_predictors.Allocate(nvert);
227
0
            m_predictors.Clear();
228
0
        }
229
0
        else
230
0
        {
231
0
            mask += (O3DGC_SC3DMC_BINARIZATION_AC_EGC & 7)<<4;
232
0
            const unsigned int NMAX = numFloatArray * dimFloatArray * 8 + 100;
233
0
            if ( m_sizeBufferAC < NMAX )
234
0
            {
235
0
                delete [] m_bufferAC;
236
0
                m_sizeBufferAC = NMAX;
237
0
                m_bufferAC     = new unsigned char [m_sizeBufferAC];
238
0
            }
239
0
            ace.set_buffer(NMAX, m_bufferAC);
240
0
            ace.start_encoder();
241
0
            ace.ExpGolombEncode(0, 0, bModel0, bModel1);
242
0
            ace.ExpGolombEncode(M, 0, bModel0, bModel1);
243
0
        }
244
0
        bstream.WriteUInt32(0, m_streamType);
245
0
        bstream.WriteUChar(mask, m_streamType);
246
247
#ifdef DEBUG_VERBOSE
248
        printf("FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
249
        fprintf(g_fileDebugSC3DMCEnc, "FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
250
#endif //DEBUG_VERBOSE
251
252
0
        if (predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
253
0
        {
254
0
            const Real curMinFloatArray[2] = {(Real)(-2.0),(Real)(-2.0)};
255
0
            const Real curMaxFloatArray[2] = {(Real)(2.0),(Real)(2.0)};
256
0
            if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
257
0
            {
258
0
                for(unsigned long i = 0; i < numFloatArray; ++i)
259
0
                {
260
0
                    bstream.WriteIntASCII(m_predictors[i]);
261
0
                }
262
0
            }
263
0
            else
264
0
            {
265
0
                Adaptive_Data_Model dModel(12);
266
0
                for(unsigned long i = 0; i < numFloatArray; ++i)
267
0
                {
268
0
                    ace.encode(IntToUInt(m_predictors[i]), dModel);
269
0
                }
270
0
            }
271
0
            QuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, curMinFloatArray, curMaxFloatArray, nQBits + 1);
272
0
        }
273
0
        else
274
0
        {
275
0
            QuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, minFloatArray, maxFloatArray, nQBits);
276
0
        }
277
278
0
        for (long vm=0; vm < nvert; ++vm) 
279
0
        {
280
0
            nPred = 0;
281
0
            v     = invVMap[vm];
282
0
            assert( v >= 0 && v < nvert);
283
0
            if ( v2T.GetNumNeighbors(v) > 0 && 
284
0
                 predMode != O3DGC_SC3DMC_NO_PREDICTION)
285
0
            {
286
0
                int u0 = v2T.Begin(v);
287
0
                int u1 = v2T.End(v);
288
0
                for (long u = u0; u < u1; u++) 
289
0
                {
290
0
                    long ta = v2T.GetNeighbor(u);
291
0
                    if ( predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION )
292
0
                    {
293
0
                        long a,b;
294
0
                        if ((long) triangles[ta*3] == v)
295
0
                        {
296
0
                            a = triangles[ta*3 + 1];
297
0
                            b = triangles[ta*3 + 2];
298
0
                        }
299
0
                        else if ((long) triangles[ta*3 + 1] == v)
300
0
                        {
301
0
                            a = triangles[ta*3 + 0];
302
0
                            b = triangles[ta*3 + 2];
303
0
                        }
304
0
                        else
305
0
                        {
306
0
                            a = triangles[ta*3 + 0];
307
0
                            b = triangles[ta*3 + 1];
308
0
                        }
309
0
                        if ( vmap[a] < vm && vmap[b] < vm)
310
0
                        {
311
0
                            int u0 = v2T.Begin(a);
312
0
                            int u1 = v2T.End(a);
313
0
                            for (long u = u0; u < u1; u++) 
314
0
                            {
315
0
                                long tb = v2T.GetNeighbor(u);
316
0
                                long c = -1;
317
0
                                bool foundB = false;
318
0
                                for(long k = 0; k < 3; ++k)
319
0
                                {
320
0
                                    long x = triangles[tb*3 + k];
321
0
                                    if (x == b)
322
0
                                    {
323
0
                                        foundB = true;
324
0
                                    }
325
0
                                    if (vmap[x] < vm && x != a && x != b)
326
0
                                    {
327
0
                                        c = x;
328
0
                                    }
329
0
                                }
330
0
                                if (c != -1 && foundB)
331
0
                                {
332
0
                                    SC3DMCTriplet id = {min(vmap[a], vmap[b]), max(vmap[a], vmap[b]), -vmap[c]-1};
333
0
                                    unsigned long p = Insert(id, nPred, m_neighbors);
334
0
                                    if (p != 0xFFFFFFFF)
335
0
                                    {
336
0
                                        for (unsigned long i = 0; i < dimFloatArray; i++) 
337
0
                                        {
338
0
                                            m_neighbors[p].m_pred[i] = m_quantFloatArray[a*stride+i] + 
339
0
                                                                       m_quantFloatArray[b*stride+i] - 
340
0
                                                                       m_quantFloatArray[c*stride+i];
341
0
                                        } 
342
0
                                    }
343
0
                                }
344
0
                            }
345
0
                        }
346
0
                    }
347
0
                    if ( predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION  ||
348
0
                         predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION ||
349
0
                         predMode == O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION )
350
0
                    {
351
0
                        for(long k = 0; k < 3; ++k)
352
0
                        {
353
0
                            long w = triangles[ta*3 + k];
354
0
                            if ( vmap[w] < vm )
355
0
                            {
356
0
                                SC3DMCTriplet id = {-1, -1, vmap[w]};
357
0
                                unsigned long p = Insert(id, nPred, m_neighbors);
358
0
                                if (p != 0xFFFFFFFF)
359
0
                                {
360
0
                                    for (unsigned long i = 0; i < dimFloatArray; i++) 
361
0
                                    {
362
0
                                        m_neighbors[p].m_pred[i] = m_quantFloatArray[w*stride+i];
363
0
                                    } 
364
0
                                }
365
0
                            }
366
0
                        }
367
0
                    }        
368
0
                }
369
0
            }
370
0
            if (nPred > 1)
371
0
            {
372
                // find best predictor
373
0
                unsigned long bestPred = 0xFFFFFFFF;
374
0
                double bestCost = O3DGC_MAX_DOUBLE;
375
0
                double cost;
376
#ifdef DEBUG_VERBOSE1
377
                    printf("\t\t vm %i\n", vm);
378
                    fprintf(g_fileDebugSC3DMCEnc, "\t\t vm %i\n", vm);
379
#endif //DEBUG_VERBOSE
380
381
0
                for (unsigned long p = 0; p < nPred; ++p)
382
0
                {
383
#ifdef DEBUG_VERBOSE1
384
                    printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
385
                    fprintf(g_fileDebugSC3DMCEnc, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
386
#endif //DEBUG_VERBOSE
387
0
                    cost = -log2((m_freqPreds[p]+1.0) / nPredictors );
388
0
                    for (unsigned long i = 0; i < dimFloatArray; ++i) 
389
0
                    {
390
#ifdef DEBUG_VERBOSE1
391
                        printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
392
                        fprintf(g_fileDebugSC3DMCEnc, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
393
#endif //DEBUG_VERBOSE
394
395
0
                        predResidual = (long) IntToUInt(m_quantFloatArray[v*stride+i] - m_neighbors[p].m_pred[i]);
396
0
                        if (predResidual < (long) M) 
397
0
                        {
398
0
                            cost += -log2((m_freqSymbols[predResidual]+1.0) / nSymbols );
399
0
                        }
400
0
                        else 
401
0
                        {
402
0
                            cost += -log2((m_freqSymbols[M] + 1.0) / nSymbols ) + log2((double) (predResidual-M));
403
0
                        }
404
0
                    }
405
0
                    if (cost < bestCost)
406
0
                    {
407
0
                        bestCost = cost;
408
0
                        bestPred = p;
409
0
                    }
410
0
                }
411
0
                if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
412
0
                {
413
0
                    m_predictors.PushBack((unsigned char) bestPred);
414
0
                }
415
0
                else
416
0
                {
417
0
                    ace.encode(bestPred, mModelPreds);
418
0
                }
419
#ifdef DEBUG_VERBOSE1
420
                    printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
421
                    fprintf(g_fileDebugSC3DMCEnc, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
422
#endif //DEBUG_VERBOSE
423
                // use best predictor
424
0
                for (unsigned long i = 0; i < dimFloatArray; ++i) 
425
0
                {
426
0
                    predResidual  = m_quantFloatArray[v*stride+i] - m_neighbors[bestPred].m_pred[i];
427
0
                    uPredResidual = IntToUInt(predResidual);
428
0
                    ++m_freqSymbols[(uPredResidual < (long) M)? uPredResidual : M];
429
430
#ifdef DEBUG_VERBOSE
431
                    printf("%i \t %i \t [%i]\n", vm*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
432
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i \t [%i]\n", vm*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
433
#endif //DEBUG_VERBOSE
434
435
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
436
0
                    {
437
0
                        bstream.WriteIntASCII(predResidual);
438
0
                    }
439
0
                    else
440
0
                    {
441
0
                        EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
442
0
                    }
443
0
                }
444
0
                ++m_freqPreds[bestPred];
445
0
                nSymbols += dimFloatArray;
446
0
                ++nPredictors;
447
0
            }
448
0
            else if ( vm > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
449
0
            {
450
0
                long prev = invVMap[vm-1];
451
0
                for (unsigned long i = 0; i < dimFloatArray; i++) 
452
0
                {
453
0
                    predResidual = m_quantFloatArray[v*stride+i] - m_quantFloatArray[prev*stride+i];
454
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
455
0
                    {
456
0
                        bstream.WriteIntASCII(predResidual);
457
0
                    }
458
0
                    else
459
0
                    {
460
0
                        EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
461
0
                    }
462
#ifdef DEBUG_VERBOSE
463
                    printf("%i \t %i\n", vm*dimFloatArray+i, predResidual);
464
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimFloatArray+i, predResidual);
465
#endif //DEBUG_VERBOSE
466
0
                }
467
0
            }
468
0
            else
469
0
            {
470
0
                for (unsigned long i = 0; i < dimFloatArray; i++) 
471
0
                {
472
0
                    predResidual = m_quantFloatArray[v*stride+i];
473
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
474
0
                    {
475
0
                        bstream.WriteUIntASCII(predResidual);
476
0
                    }
477
0
                    else
478
0
                    {
479
0
                        EncodeUIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
480
0
                    }
481
#ifdef DEBUG_VERBOSE
482
                    printf("%i \t %i\n", vm*dimFloatArray+i, predResidual);
483
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimFloatArray+i, predResidual);
484
#endif //DEBUG_VERBOSE
485
0
                }
486
0
            }
487
0
        }
488
0
        if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
489
0
        {
490
0
            unsigned long encodedBytes = ace.stop_encoder();
491
0
            for(unsigned long i = 0; i < encodedBytes; ++i)
492
0
            {
493
0
                bstream.WriteUChar8Bin(m_bufferAC[i]);
494
0
            }
495
0
        }
496
0
        bstream.WriteUInt32(start, bstream.GetSize() - start, m_streamType);
497
498
0
        if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
499
0
        {
500
0
            unsigned long start = bstream.GetSize();
501
0
            bstream.WriteUInt32ASCII(0);
502
0
            const unsigned long size       = m_predictors.GetSize();
503
0
            for(unsigned long i = 0; i < size; ++i)
504
0
            {
505
0
                bstream.WriteUCharASCII((unsigned char) m_predictors[i]);
506
0
            }
507
0
            bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
508
0
        }
509
#ifdef DEBUG_VERBOSE
510
        fflush(g_fileDebugSC3DMCEnc);
511
#endif //DEBUG_VERBOSE
512
0
        return O3DGC_OK;
513
0
    }
514
515
    template <class T>
516
    O3DGCErrorCode SC3DMCEncoder<T>::EncodeIntArray(const long * const intArray, 
517
                                                    unsigned long numIntArray,
518
                                                    unsigned long dimIntArray,
519
                                                    unsigned long stride,
520
                                                    const IndexedFaceSet<T> & ifs,
521
                                                    O3DGCSC3DMCPredictionMode predMode,
522
                                                    BinaryStream & bstream)
523
0
    {
524
0
        assert(dimIntArray <  O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
525
0
        long predResidual, v, uPredResidual;
526
0
        unsigned long nPred;
527
0
        Arithmetic_Codec ace;
528
0
        Static_Bit_Model bModel0;
529
0
        Adaptive_Bit_Model bModel1;
530
531
0
        const AdjacencyInfo & v2T         = m_triangleListEncoder.GetVertexToTriangle();
532
0
        const long * const    vmap        = m_triangleListEncoder.GetVMap();
533
0
        const long * const    invVMap     = m_triangleListEncoder.GetInvVMap();
534
0
        const T * const       triangles   = ifs.GetCoordIndex();
535
0
        const long            nvert       = (long) numIntArray;
536
0
        unsigned long         start       = bstream.GetSize();
537
0
        unsigned char         mask        = predMode & 7;
538
0
        const unsigned long   M           = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS - 1;
539
0
        unsigned long         nSymbols    = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS;
540
0
        unsigned long         nPredictors = O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS;
541
        
542
543
0
        Adaptive_Data_Model mModelValues(M+2);
544
0
        Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
545
546
0
        memset(m_freqSymbols, 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS);
547
0
        memset(m_freqPreds  , 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS);
548
0
        if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
549
0
        {
550
0
            mask += (O3DGC_SC3DMC_BINARIZATION_ASCII & 7)<<4;
551
0
            m_predictors.Allocate(nvert);
552
0
            m_predictors.Clear();
553
0
        }
554
0
        else
555
0
        {
556
0
            mask += (O3DGC_SC3DMC_BINARIZATION_AC_EGC & 7)<<4;
557
0
            const unsigned int NMAX = numIntArray * dimIntArray * 8 + 100;
558
0
            if ( m_sizeBufferAC < NMAX )
559
0
            {
560
0
                delete [] m_bufferAC;
561
0
                m_sizeBufferAC = NMAX;
562
0
                m_bufferAC     = new unsigned char [m_sizeBufferAC];
563
0
            }
564
0
            ace.set_buffer(NMAX, m_bufferAC);
565
0
            ace.start_encoder();
566
0
            ace.ExpGolombEncode(0, 0, bModel0, bModel1);
567
0
            ace.ExpGolombEncode(M, 0, bModel0, bModel1);
568
0
        }
569
0
        bstream.WriteUInt32(0, m_streamType);
570
0
        bstream.WriteUChar(mask, m_streamType);
571
572
#ifdef DEBUG_VERBOSE
573
        printf("IntArray (%i, %i)\n", numIntArray, dimIntArray);
574
        fprintf(g_fileDebugSC3DMCEnc, "IntArray (%i, %i)\n", numIntArray, dimIntArray);
575
#endif //DEBUG_VERBOSE
576
577
0
        for (long vm=0; vm < nvert; ++vm) 
578
0
        {
579
0
            nPred = 0;
580
0
            v     = invVMap[vm];
581
0
            assert( v >= 0 && v < nvert);
582
0
            if ( v2T.GetNumNeighbors(v) > 0 && 
583
0
                 predMode != O3DGC_SC3DMC_NO_PREDICTION)
584
0
            {
585
0
                int u0 = v2T.Begin(v);
586
0
                int u1 = v2T.End(v);
587
0
                for (long u = u0; u < u1; u++) 
588
0
                {
589
0
                    long ta = v2T.GetNeighbor(u);
590
0
                    for(long k = 0; k < 3; ++k)
591
0
                    {
592
0
                        long w = triangles[ta*3 + k];
593
0
                        if ( vmap[w] < vm )
594
0
                        {
595
0
                            SC3DMCTriplet id = {-1, -1, vmap[w]};
596
0
                            unsigned long p = Insert(id, nPred, m_neighbors);
597
0
                            if (p != 0xFFFFFFFF)
598
0
                            {
599
0
                                for (unsigned long i = 0; i < dimIntArray; i++) 
600
0
                                {
601
0
                                    m_neighbors[p].m_pred[i] = intArray[w*stride+i];
602
0
                                } 
603
0
                            }
604
0
                        }
605
0
                    }
606
0
                }
607
0
            }
608
0
            if (nPred > 1)
609
0
            {
610
                // find best predictor
611
0
                unsigned long bestPred = 0xFFFFFFFF;
612
0
                double bestCost = O3DGC_MAX_DOUBLE;
613
0
                double cost;
614
#ifdef DEBUG_VERBOSE1
615
                    printf("\t\t vm %i\n", vm);
616
                    fprintf(g_fileDebugSC3DMCEnc, "\t\t vm %i\n", vm);
617
#endif //DEBUG_VERBOSE
618
619
0
                for (unsigned long p = 0; p < nPred; ++p)
620
0
                {
621
#ifdef DEBUG_VERBOSE1
622
                    printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
623
                    fprintf(g_fileDebugSC3DMCEnc, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
624
#endif //DEBUG_VERBOSE
625
0
                    cost = -log2((m_freqPreds[p]+1.0) / nPredictors );
626
0
                    for (unsigned long i = 0; i < dimIntArray; ++i) 
627
0
                    {
628
#ifdef DEBUG_VERBOSE1
629
                        printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
630
                        fprintf(g_fileDebugSC3DMCEnc, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
631
#endif //DEBUG_VERBOSE
632
633
0
                        predResidual = (long) IntToUInt(intArray[v*stride+i] - m_neighbors[p].m_pred[i]);
634
0
                        if (predResidual < (long) M) 
635
0
                        {
636
0
                            cost += -log2((m_freqSymbols[predResidual]+1.0) / nSymbols );
637
0
                        }
638
0
                        else 
639
0
                        {
640
0
                            cost += -log2((m_freqSymbols[M] + 1.0) / nSymbols ) + log2((double) (predResidual-M));
641
0
                        }
642
0
                    }
643
0
                    if (cost < bestCost)
644
0
                    {
645
0
                        bestCost = cost;
646
0
                        bestPred = p;
647
0
                    }
648
0
                }
649
0
                if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
650
0
                {
651
0
                    m_predictors.PushBack((unsigned char) bestPred);
652
0
                }
653
0
                else
654
0
                {
655
0
                    ace.encode(bestPred, mModelPreds);
656
0
                }
657
#ifdef DEBUG_VERBOSE1
658
                    printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
659
                    fprintf(g_fileDebugSC3DMCEnc, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
660
#endif //DEBUG_VERBOSE
661
                // use best predictor
662
0
                for (unsigned long i = 0; i < dimIntArray; ++i) 
663
0
                {
664
0
                    predResidual  = intArray[v*stride+i] - m_neighbors[bestPred].m_pred[i];
665
0
                    uPredResidual = IntToUInt(predResidual);
666
0
                    ++m_freqSymbols[(uPredResidual < (long) M)? uPredResidual : M];
667
668
#ifdef DEBUG_VERBOSE
669
                    printf("%i \t %i \t [%i]\n", vm*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
670
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i \t [%i]\n", vm*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
671
#endif //DEBUG_VERBOSE
672
673
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
674
0
                    {
675
0
                        bstream.WriteIntASCII(predResidual);
676
0
                    }
677
0
                    else
678
0
                    {
679
0
                        EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
680
0
                    }
681
0
                }
682
0
                ++m_freqPreds[bestPred];
683
0
                nSymbols += dimIntArray;
684
0
                ++nPredictors;
685
0
            }
686
0
            else if ( vm > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
687
0
            {
688
0
                long prev = invVMap[vm-1];
689
0
                for (unsigned long i = 0; i < dimIntArray; i++) 
690
0
                {
691
0
                    predResidual = intArray[v*stride+i] - intArray[prev*stride+i];
692
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
693
0
                    {
694
0
                        bstream.WriteIntASCII(predResidual);
695
0
                    }
696
0
                    else
697
0
                    {
698
0
                        EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
699
0
                    }
700
#ifdef DEBUG_VERBOSE
701
                    printf("%i \t %i\n", vm*dimIntArray+i, predResidual);
702
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimIntArray+i, predResidual);
703
#endif //DEBUG_VERBOSE
704
0
                }
705
0
            }
706
0
            else
707
0
            {
708
0
                for (unsigned long i = 0; i < dimIntArray; i++) 
709
0
                {
710
0
                    predResidual = intArray[v*stride+i];
711
0
                    if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
712
0
                    {
713
0
                        bstream.WriteUIntASCII(predResidual);
714
0
                    }
715
0
                    else
716
0
                    {
717
0
                        EncodeUIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
718
0
                    }
719
#ifdef DEBUG_VERBOSE
720
                    printf("%i \t %i\n", vm*dimIntArray+i, predResidual);
721
                    fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimIntArray+i, predResidual);
722
#endif //DEBUG_VERBOSE
723
0
                }
724
0
            }
725
0
        }
726
0
        if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
727
0
        {
728
0
            unsigned long encodedBytes = ace.stop_encoder();
729
0
            for(unsigned long i = 0; i < encodedBytes; ++i)
730
0
            {
731
0
                bstream.WriteUChar8Bin(m_bufferAC[i]);
732
0
            }
733
0
        }
734
0
        bstream.WriteUInt32(start, bstream.GetSize() - start, m_streamType);
735
736
0
        if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
737
0
        {
738
0
            unsigned long start = bstream.GetSize();
739
0
            bstream.WriteUInt32ASCII(0);
740
0
            const unsigned long size       = m_predictors.GetSize();
741
0
            for(unsigned long i = 0; i < size; ++i)
742
0
            {
743
0
                bstream.WriteUCharASCII((unsigned char) m_predictors[i]);
744
0
            }
745
0
            bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
746
0
        }
747
#ifdef DEBUG_VERBOSE
748
        fflush(g_fileDebugSC3DMCEnc);
749
#endif //DEBUG_VERBOSE
750
0
        return O3DGC_OK;
751
0
    }
752
    template <class T>
753
    O3DGCErrorCode SC3DMCEncoder<T>::ProcessNormals(const IndexedFaceSet<T> & ifs)
754
0
    {
755
0
        const long nvert               = (long) ifs.GetNNormal();
756
0
        const unsigned long normalSize = ifs.GetNNormal() * 2;
757
0
        if (m_normalsSize < normalSize)
758
0
        {
759
0
            delete [] m_normals;
760
0
            m_normalsSize = normalSize;
761
0
            m_normals     = new Real [normalSize];
762
0
        }                                  
763
0
        const AdjacencyInfo & v2T          = m_triangleListEncoder.GetVertexToTriangle();
764
0
        const long * const    invVMap      = m_triangleListEncoder.GetInvVMap();
765
0
        const T * const       triangles    = ifs.GetCoordIndex();
766
0
        const Real * const originalNormals = ifs.GetNormal();
767
0
        Vec3<long> p1, p2, p3, n0, nt;
768
0
        Vec3<Real> n1;
769
0
        long na0 = 0, nb0 = 0;
770
0
        Real rna0, rnb0, na1 = 0, nb1 = 0, norm0, norm1;
771
0
        char ni0 = 0, ni1 = 0;
772
0
        long a, b, c, v;
773
0
        m_predictors.Clear();
774
0
        for (long i=0; i < nvert; ++i) 
775
0
        {
776
0
            v = invVMap[i];
777
0
            n0.X() = 0;
778
0
            n0.Y() = 0;
779
0
            n0.Z() = 0;
780
0
            int u0 = v2T.Begin(v);
781
0
            int u1 = v2T.End(v);
782
0
            for (long u = u0; u < u1; u++) 
783
0
            {
784
0
                long ta = v2T.GetNeighbor(u);
785
0
                a = triangles[ta*3 + 0];
786
0
                b = triangles[ta*3 + 1];
787
0
                c = triangles[ta*3 + 2];
788
0
                p1.X() = m_quantFloatArray[3*a];
789
0
                p1.Y() = m_quantFloatArray[3*a+1];
790
0
                p1.Z() = m_quantFloatArray[3*a+2];
791
0
                p2.X() = m_quantFloatArray[3*b];
792
0
                p2.Y() = m_quantFloatArray[3*b+1];
793
0
                p2.Z() = m_quantFloatArray[3*b+2];
794
0
                p3.X() = m_quantFloatArray[3*c];
795
0
                p3.Y() = m_quantFloatArray[3*c+1];
796
0
                p3.Z() = m_quantFloatArray[3*c+2];
797
0
                nt  = (p2-p1)^(p3-p1);
798
0
                n0 += nt;
799
0
            }
800
0
            norm0 = (Real) n0.GetNorm();
801
0
            if (norm0 == 0.0)
802
0
            {
803
0
                norm0 = 1.0;
804
0
            }
805
0
            SphereToCube(n0.X(), n0.Y(), n0.Z(), na0, nb0, ni0);
806
0
            rna0 = na0 / norm0;
807
0
            rnb0 = nb0 / norm0;
808
809
0
            n1.X() = originalNormals[3*v];
810
0
            n1.Y() = originalNormals[3*v+1];
811
0
            n1.Z() = originalNormals[3*v+2];
812
0
            norm1 = (Real) n1.GetNorm();
813
0
            if (norm1 != 0.0)
814
0
            {
815
0
                n1.X() /= norm1;
816
0
                n1.Y() /= norm1;
817
0
                n1.Z() /= norm1;
818
0
            }
819
0
            SphereToCube(n1.X(), n1.Y(), n1.Z(), na1, nb1, ni1);
820
0
            m_predictors.PushBack(ni1 - ni0);
821
0
            if ( (ni1 >> 1) != (ni0 >> 1) )
822
0
            {
823
0
                rna0 = (Real)0.0;
824
0
                rnb0 = (Real)0.0;
825
0
            }
826
0
            m_normals[2*v]   = na1 - rna0;
827
0
            m_normals[2*v+1] = nb1 - rnb0;
828
829
#ifdef DEBUG_VERBOSE1
830
            printf("n0 \t %i \t %i \t %i \t %i (%f, %f)\n", i, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
831
            fprintf(g_fileDebugSC3DMCEnc,"n0 \t %i \t %i \t %i \t %i (%f, %f)\n", i, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
832
#endif //DEBUG_VERBOSE
833
834
#ifdef DEBUG_VERBOSE1
835
            printf("normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n", i, n1.X(), n1.Y(), n1.Z(), ni1, na1, nb1, rna0, rnb0);
836
            fprintf(g_fileDebugSC3DMCEnc, "normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n", i, n1.X(), n1.Y(), n1.Z(), ni1, na1, nb1, rna0, rnb0);
837
#endif //DEBUG_VERBOSE
838
839
0
        }
840
0
        return O3DGC_OK;
841
0
    }
842
843
    template <class T>
844
    O3DGCErrorCode SC3DMCEncoder<T>::EncodePayload(const SC3DMCEncodeParams & params, 
845
                                                   const IndexedFaceSet<T> & ifs, 
846
                                                   BinaryStream & bstream)
847
0
    {
848
#ifdef DEBUG_VERBOSE
849
        g_fileDebugSC3DMCEnc = fopen("tfans_enc_main.txt", "w");
850
#endif //DEBUG_VERBOSE
851
852
        // encode triangle list        
853
0
        m_triangleListEncoder.SetStreamType(params.GetStreamType());
854
0
        m_stats.m_streamSizeCoordIndex = bstream.GetSize();
855
0
        Timer timer;
856
0
        timer.Tic();
857
0
        m_triangleListEncoder.Encode(ifs.GetCoordIndex(), ifs.GetIndexBufferID(), ifs.GetNCoordIndex(), ifs.GetNCoord(), bstream);
858
0
        timer.Toc();
859
0
        m_stats.m_timeCoordIndex       = timer.GetElapsedTime();
860
0
        m_stats.m_streamSizeCoordIndex = bstream.GetSize() - m_stats.m_streamSizeCoordIndex;
861
862
        // encode coord
863
0
        m_stats.m_streamSizeCoord = bstream.GetSize();
864
0
        timer.Tic();
865
0
        if (ifs.GetNCoord() > 0)
866
0
        {
867
0
            EncodeFloatArray(ifs.GetCoord(), ifs.GetNCoord(), 3, 3, ifs.GetCoordMin(), ifs.GetCoordMax(), 
868
0
                                params.GetCoordQuantBits(), ifs, params.GetCoordPredMode(), bstream);
869
0
        }
870
0
        timer.Toc();
871
0
        m_stats.m_timeCoord       = timer.GetElapsedTime();
872
0
        m_stats.m_streamSizeCoord = bstream.GetSize() - m_stats.m_streamSizeCoord;
873
874
875
        // encode Normal
876
0
        m_stats.m_streamSizeNormal = bstream.GetSize();
877
0
        timer.Tic();
878
0
        if (ifs.GetNNormal() > 0)
879
0
        {
880
0
            if (params.GetNormalPredMode() == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
881
0
            {
882
0
                ProcessNormals(ifs);
883
0
                EncodeFloatArray(m_normals, ifs.GetNNormal(), 2, 2, ifs.GetNormalMin(), ifs.GetNormalMax(), 
884
0
                params.GetNormalQuantBits(), ifs, params.GetNormalPredMode(), bstream);
885
0
            }
886
0
            else
887
0
            {
888
0
                EncodeFloatArray(ifs.GetNormal(), ifs.GetNNormal(), 3, 3, ifs.GetNormalMin(), ifs.GetNormalMax(), 
889
0
                params.GetNormalQuantBits(), ifs, params.GetNormalPredMode(), bstream);
890
0
            }
891
0
        }
892
0
        timer.Toc();
893
0
        m_stats.m_timeNormal       = timer.GetElapsedTime();
894
0
        m_stats.m_streamSizeNormal = bstream.GetSize() - m_stats.m_streamSizeNormal;
895
896
897
        // encode FloatAttribute
898
0
        for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
899
0
        {
900
0
            m_stats.m_streamSizeFloatAttribute[a] = bstream.GetSize();
901
0
            timer.Tic();
902
0
            EncodeFloatArray(ifs.GetFloatAttribute(a), ifs.GetNFloatAttribute(a), 
903
0
                             ifs.GetFloatAttributeDim(a), ifs.GetFloatAttributeDim(a),
904
0
                             ifs.GetFloatAttributeMin(a), ifs.GetFloatAttributeMax(a), 
905
0
                             params.GetFloatAttributeQuantBits(a), ifs, 
906
0
                             params.GetFloatAttributePredMode(a), bstream);
907
0
            timer.Toc();
908
0
            m_stats.m_timeFloatAttribute[a]       = timer.GetElapsedTime();
909
0
            m_stats.m_streamSizeFloatAttribute[a] = bstream.GetSize() - m_stats.m_streamSizeFloatAttribute[a];
910
0
        }
911
912
        // encode IntAttribute
913
0
        for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
914
0
        {
915
0
            m_stats.m_streamSizeIntAttribute[a] = bstream.GetSize();
916
0
            timer.Tic();
917
0
            EncodeIntArray(ifs.GetIntAttribute(a), ifs.GetNIntAttribute(a), ifs.GetIntAttributeDim(a), 
918
0
                           ifs.GetIntAttributeDim(a), ifs, params.GetIntAttributePredMode(a), bstream);
919
0
            timer.Toc();
920
0
            m_stats.m_timeIntAttribute[a]       = timer.GetElapsedTime();
921
0
            m_stats.m_streamSizeIntAttribute[a] = bstream.GetSize() - m_stats.m_streamSizeIntAttribute[a];
922
0
        }
923
#ifdef DEBUG_VERBOSE
924
        fclose(g_fileDebugSC3DMCEnc);
925
#endif //DEBUG_VERBOSE
926
0
        return O3DGC_OK;
927
0
    }
928
} // namespace o3dgc
929
930
#ifdef _MSC_VER
931
#    pragma warning(pop)
932
#endif // _MSC_VER
933
934
#endif // O3DGC_SC3DMC_ENCODER_INL
935
936