"Fossies" - the Fresh Open Source Software Archive

Member "aqsis-1.8.2/libs/tex/pointcloud/pointcloud.cpp" (24 Aug 2012, 19782 Bytes) of package /linux/privat/aqsis-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Aqsis
    2 // Copyright (C) 2001, Paul C. Gregory and the other authors and contributors
    3 // All rights reserved.
    4 //
    5 // Redistribution and use in source and binary forms, with or without
    6 // modification, are permitted provided that the following conditions are met:
    7 //
    8 // * Redistributions of source code must retain the above copyright notice,
    9 //   this list of conditions and the following disclaimer.
   10 // * Redistributions in binary form must reproduce the above copyright notice,
   11 //   this list of conditions and the following disclaimer in the documentation
   12 //   and/or other materials provided with the distribution.
   13 // * Neither the name of the software's owners nor the names of its
   14 //   contributors may be used to endorse or promote products derived from this
   15 //   software without specific prior written permission.
   16 //
   17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 // POSSIBILITY OF SUCH DAMAGE.
   28 //
   29 // (This is the New BSD license)
   30 
   31 /** \file
   32         \brief declares an api for points information compatible with prman, 3delight and pixie
   33         \author Michel Joron  (joron@sympatico.ca)
   34 */
   35 #include <aqsis/aqsis.h>
   36 
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 #include <limits.h>
   41 #include <float.h>
   42 #include <math.h>
   43 
   44 // The file structure is equivalent to the following.
   45 // Except it is in binary.
   46 //----------------------------------
   47 // 'Aqsis_PTC' 1
   48 // [Number of Channels] 1 [*optional]
   49 // "Ci" "color"
   50 // [Size of Channels] 3
   51 // [World2Eye] 1/0 *Optional
   52 //   Matrix[0], Matrix[1], ... Matrix[15] *Optional
   53 // [World2NDC] 1/0 *Optional
   54 //   Matrix[0], Matrix[1], ... Matrix[15] *Optional
   55 // [Format] 1/0 *Optinal
   56 //    X, Y, AspectRation] *Optional
   57 // [BoundingBox] 6
   58 // -100.955681 99.044319 -90.713783 109.273087 340.360199 505.259033
   59 // [Number of Data] 26812
   60 // -100.955681 9.275940 440.359985 1.000000 0.000000 -0.000000 1.000000
   61 // 0.052700 0.082552 0.032063
   62 // Point[0], Point[1], Point[2], Normal[0], Normal[1], Normal[2], Radius
   63 // User_Data[0], User_Data[1], ...
   64 // ...
   65 // -------
   66 //
   67 
   68 #include    <aqsis/ri/pointcloud.h>
   69 
   70 #define PTCNAME    "Aqsis_PTC"
   71 #define PTCVERSION 1
   72 
   73 typedef struct
   74 {
   75     float point[3];
   76     float normal[3];
   77     float radius;
   78     float *user_data;
   79 }
   80 PtcPointCloudKey;
   81 
   82 typedef struct
   83 {
   84     char  signature;
   85     char  filename[1024];
   86     char  nvars;
   87     char **vartypes;
   88     char **varnames;
   89     float world2eye[16];
   90     float world2ndc[16];
   91     float format[3];
   92 // At runtime the rest is filled by the file content itself
   93     FILE    *fp;
   94     int   npoints;
   95     int   seek;
   96     float bbox[6];
   97     int   datasize;
   98     int   maxpoints;
   99     PtcPointCloudKey *key;
  100 }
  101 PtcPointCloudHandle;
  102 
  103 
  104 #define MIN(a, b)  (((a) <= (b)) ? (a) : (b))
  105 #define MAX(a, b)  (((a) >= (b)) ? (a) : (b))
  106 
  107 int diff(const void *a, const void *b)
  108 {
  109     PtcPointCloudKey *A = (PtcPointCloudKey *) a;
  110     PtcPointCloudKey *B = (PtcPointCloudKey *) b;
  111     return  memcmp((void *) A->point, (void *) B->point, sizeof(float) * 3);
  112 }
  113 //---------------------------------------------------------------------
  114 /**
  115 * This function opens a given file for reading
  116 * \param filename The complete path to the point cloud file
  117 * \param nvars A pointer to an int that will be filled with the total number of channels
  118 *     in the point cloud file.
  119 * \param varnames A pointer to an array of const char * that will hold the name of each
  120 *variable.
  121 * \param vartypes A pointer to an array of const char * that will hold the type of each
  122 *variable. Types are string representing the type of the variable as declared
  123 *in the shading language (color, point, float, normal, . . . etc).
  124 *
  125 *This function could fail if the file is not accessible or is not a valid point cloud file, in which case null is returned.
  126 *
  127 *note: This API call is badly designed since the caller cannot know the size
  128 *of vartypes and varnames in advance. But for compatibly reasons with other
  129 *software we decided to stick with this API. A simple and secure workaround goes
  130 *as follows:
  131 *1. Call PtcOpenPointCloudFile with vartypes and varnames set to null to
  132 *obtain nvars.
  133 *2. Close the returned file handle.
  134 *3. Allocate arrays big enough for vartypes and varnames since now we know
  135 *their size.
  136 *4. Call PtcOpenPointCloudFile again with the allocated arrays.
  137 * \return a file handle than shall be used in other reading calls.
  138 */
  139 extern "C" PtcPointCloud PtcOpenPointCloudFile ( const char *filename, int *nvars, const char **vartypes, const char **varnames )
  140 {
  141     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *) (new PtcPointCloudHandle);
  142     char exist;
  143 
  144     memset((void*)ptc, 0, sizeof(PtcPointCloudHandle));
  145     strcpy(ptc->filename, filename);
  146     ptc->fp = fopen(filename, "rb");
  147     if (ptc->fp)
  148     {
  149         char name[80];
  150         fread(name, 1, strlen(PTCNAME) + 1, ptc->fp);
  151         fread(&ptc->signature, 1, 1, ptc->fp);
  152 
  153         if (strcmp(name, PTCNAME) == 0 && ptc->signature == PTCVERSION)
  154         {
  155          int i;
  156             fread(&ptc->nvars, 1, 1, ptc->fp);
  157             if (ptc->nvars > 0)
  158             {
  159                 ptc->vartypes = (char **) malloc(ptc->nvars * sizeof(char *));
  160                 ptc->varnames = (char **) malloc(ptc->nvars * sizeof(char *));
  161                 for (int i = 0; i < ptc->nvars; i++)
  162                 {
  163                     unsigned char size[2];
  164                     fread(size, 1, 2, ptc->fp);
  165                     ptc->vartypes[i] = (char *) malloc(size[0]);
  166                     ptc->varnames[i] = (char *) malloc(size[1]);
  167                     fread(ptc->vartypes[i], 1, size[0], ptc->fp);
  168                     fread(ptc->varnames[i], 1, size[1], ptc->fp);
  169                 }
  170             }
  171 
  172             fread(&ptc->datasize, sizeof(int), 1, ptc->fp);
  173 
  174             fread(&exist, 1, 1, ptc->fp);
  175             if (exist == 1)
  176             {
  177                 fread(ptc->world2eye, sizeof(float), 16, ptc->fp);
  178                 exist = 0;
  179             }
  180 
  181             fread(&exist, 1, 1, ptc->fp);
  182             if (exist == 1)
  183             {
  184                 fread(ptc->world2ndc, sizeof(float), 16, ptc->fp);
  185                 exist = 0;
  186             }
  187 
  188             fread(&exist, 1, 1, ptc->fp);
  189             if (exist == 1)
  190             {
  191                 fread(ptc->format, sizeof(float), 3, ptc->fp);
  192                 exist = 0;
  193             }
  194 
  195             fread(ptc->bbox, sizeof(float), 6, ptc->fp);
  196 
  197             fread(&ptc->npoints, sizeof(int), 1, ptc->fp);
  198 
  199             if (ptc->npoints)
  200             {
  201                 ptc->maxpoints = ptc->npoints;
  202 
  203                 ptc->key = (PtcPointCloudKey *) (malloc(ptc->maxpoints * sizeof(PtcPointCloudKey) ));
  204 
  205                 for (i = 0; i < ptc->npoints; i++)
  206                 {
  207                     fread(ptc->key[i].point, sizeof(float), 3, ptc->fp);
  208                     fread(ptc->key[i].normal, sizeof(float), 3, ptc->fp);
  209                     fread(&ptc->key[i].radius, sizeof(float), 1, ptc->fp);
  210                     ptc->key[i].user_data = (float *) (malloc(ptc->datasize * sizeof(float) ));
  211                     fread(ptc->key[i].user_data, sizeof(float), ptc->datasize, ptc->fp);
  212                 }
  213             }
  214 
  215             if (nvars) *nvars = ptc->nvars;
  216             if (vartypes) 
  217          {
  218             for (i=0; i < ptc->nvars; i++)
  219             {
  220                vartypes[i] = ptc->vartypes[i];
  221             }
  222          }
  223             if (varnames) 
  224          {
  225             for (i=0; i < ptc->nvars; i++)
  226             {
  227                varnames[i] = ptc->varnames[i];
  228             }
  229          }
  230             fclose(ptc->fp);
  231             ptc->fp = NULL;
  232         }
  233         else
  234         {
  235             ptc->signature = 0;
  236             delete ptc;
  237             ptc = NULL;
  238         }
  239     }
  240 
  241     return (PtcPointCloud)(ptc);
  242 }
  243 
  244 
  245 //---------------------------------------------------------------------
  246 /**
  247 *This function returns informations about a point cloud file. Accepted requests are:
  248 *\param pointcloud  A handle to the point cloud file as returned by PtcOpenPointCloudFile
  249 *\param request     The name of the information needed. The following requests are accepted:
  250 *        'npoints' : Number of points in the point cloud file. C++ data type is an integer
  251 *        'bbox'    : The bounding box of the point cloud. Will return an array of six floats:
  252 *               min x, min y, min z, max x, max y and max z.
  253 *        'datasize': The number of floats needed to store each data point. C++ data type is an integer.
  254 *        'world2eye': The world to eye (world to camera) transformation matrix. Will return an
  255 *               array of 16 floats.
  256 *        'world2ndc': The world to NDC transformation matrix. Will return an array of 16 floats.
  257 *        'format'   : The resolution of the render that generated the point cloud file. Three floats will be returned: x resolution, y resolution
  258 *               and aspect ratio.
  259 *\param result     A pointer to an array large enough to hold the returned informations.
  260 *\return           1 if the request is successful, 0 otherwise.
  261 *note: Some point cloud files generated may not contain the  'format', `world2eye' or 'world2ndc' information.
  262 */
  263 extern "C" int PtcGetPointCloudInfo ( PtcPointCloud pointcloud, const char *request, void *result )
  264 {
  265     int error = 1;
  266     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  267     if (!ptc || ptc->signature != PTCVERSION)
  268     {
  269         error = 0;
  270     }
  271     else
  272     {
  273         if (strcmp(request, "npoints") == 0)
  274         {
  275             *(int *)(result) = ptc->npoints;
  276         }
  277         else if (strcmp(request, "bbox") == 0)
  278         {
  279             float *bbox = (float*) ( result );
  280             for (int i = 0; i < 6; i++)
  281             {
  282                 bbox[i] = ptc->bbox[i];
  283             }
  284         }
  285         else if (strcmp(request, "datasize") == 0)
  286         {
  287             *(int *)(result) = ptc->datasize;
  288         }
  289         else if (strcmp(request, "world2eye") == 0)
  290         {
  291             float *world2eye = (float*)  ( result );
  292             for (int i = 0; i < 16; i++)
  293             {
  294                 world2eye[i] = ptc->world2eye[i];
  295             }
  296         }
  297         else if (strcmp(request, "world2ndc") == 0)
  298         {
  299             float *world2ndc = (float*)  ( result );
  300             for (int i = 0; i < 16; i++)
  301             {
  302                 world2ndc[i] = ptc->world2ndc[i];
  303             }
  304         }
  305         else if (strcmp(request, "format") == 0)
  306         {
  307             float *format = (float*)  ( result );
  308             for (int i = 0; i < 3; i++)
  309             {
  310                 format[i] = ptc->format[i];
  311             }
  312         }
  313         else
  314         {
  315             error = 0;
  316         }
  317     }
  318 
  319 // look within the file to see what is about the request information.
  320     return error;
  321 }
  322 
  323 //---------------------------------------------------------------------
  324 /**
  325 * Reads next point from the point cloud file. The parameters are:
  326 * \param pointcloud  The handle to the point cloud file as returned by
  327 *                  PtcOpenPointCloudFile.
  328 * \param point       A pointer to a point (three floats) that will be filled with current 'point' position.
  329 * \param normal      A pointer to a point (three floats) that will be filled with current 'point' normal.
  330 * \param radius      A pointer to float that will be filled with point's radius. The area of the micro-polygon that generated this sample is radius * radius * 4.
  331 * \param user_data   A pointer to a user buffer of a size big enough to hold all the variables attached to a point.
  332 * The size of the buffer, in floats, can be obtained
  333 * by calling PtcGetPointCloudInfo with request set to 'datasize'.
  334 *
  335 * \return 1 if the operation is successful, 0 otherwise.
  336 * note: normal, radius and user data can be null if their value is not needed.
  337 *       point is read to know which data to read
  338 */
  339 extern "C" int PtcReadDataPoint ( PtcPointCloud pointcloud, float *point, float*normal, float *radius, float *user_data )
  340 {
  341     int error = 1;
  342     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  343 
  344     if (!ptc || (ptc->signature != PTCVERSION || ptc->seek >= ptc->npoints))
  345     {
  346         error = 0;
  347     }
  348     else
  349     {
  350         // reject points outside the bounding box
  351         int seek = ptc->seek;
  352 
  353         ptc->seek++;
  354 
  355         // Try the previous value
  356         if (seek < ptc->npoints)
  357         {
  358             if (point != NULL)
  359             {
  360                 memcpy(point,  ptc->key[seek].point, 3 * sizeof(float));
  361             }
  362             if (normal != NULL)
  363             {
  364                 memcpy(normal,  ptc->key[seek].normal, 3 * sizeof(float));
  365             }
  366             if (user_data != NULL)
  367             {
  368                 memcpy(user_data, ptc->key[seek].user_data, ptc->datasize * sizeof(float));
  369             }
  370             if (radius != NULL)
  371             {
  372                 *radius =  ptc->key[seek].radius;
  373             }
  374         }
  375 
  376     }
  377 
  378     return error;
  379 }
  380 
  381 extern "C" int PtcFindDataPoint ( PtcPointCloud pointcloud, float *point, float*normal, float *radius, float *user_data )
  382 {
  383     int error = 1;
  384     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  385 
  386     if (!ptc || (ptc->signature != PTCVERSION || ptc->seek >= ptc->npoints))
  387     {
  388         error = 0;
  389     }
  390     else
  391     {
  392         // reject points outside the bounding box
  393         if (point[0] < ptc->bbox[0] || point[1] < ptc->bbox[2]  || point[2] < ptc->bbox[4]  ||
  394                 point[0] > ptc->bbox[1] || point[1] > ptc->bbox[3]  || point[2] > ptc->bbox[5] )
  395             return 1;
  396 
  397         int seek = ptc->seek;
  398 
  399         // order all the read keys (once)
  400         if (ptc->seek == 0)
  401         {
  402             qsort(ptc->key, ptc->npoints, sizeof(PtcPointCloudKey), diff);
  403             ptc->seek = 1;
  404         }
  405 
  406 
  407         PtcPointCloudKey key;
  408         memcpy((void *) key.point, point, 3 * sizeof(float));
  409         PtcPointCloudKey *found = NULL;
  410         if ((found = (PtcPointCloudKey *) bsearch(&key, ptc->key, ptc->npoints, sizeof(PtcPointCloudKey), diff)))
  411         {
  412             seek = found - ptc->key;
  413         }
  414         else
  415         {
  416             // Not found !!!
  417             return 0;
  418         }
  419 
  420         // Try the previous value
  421         if (seek != -1)
  422         {
  423             if (normal != NULL)
  424             {
  425                 memcpy(normal,  ptc->key[seek].normal, 3 * sizeof(float));
  426             }
  427             if (user_data != NULL)
  428             {
  429                 memcpy(user_data, ptc->key[seek].user_data, ptc->datasize * sizeof(float));
  430             }
  431             if (radius != NULL)
  432             {
  433                 *radius =  ptc->key[seek].radius;
  434             }
  435         }
  436 
  437     }
  438 
  439     return error;
  440 }
  441 //---------------------------------------------------------------------
  442 /**
  443 * Closes a file opened with PtcOpenPointCloudFile.
  444 */
  445 extern "C" void PtcClosePointCloudFile ( PtcPointCloud pointcloud )
  446 {
  447     int error = 0;
  448     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  449     if (!ptc || ptc->signature != PTCVERSION)
  450     {
  451         error = 1;
  452     }
  453     else
  454     {
  455         if (ptc->fp != NULL)
  456         {
  457             fclose(ptc->fp);
  458             ptc->fp = NULL;
  459         }
  460         ptc->seek = 0;
  461     }
  462 }
  463 
  464 //---------------------------------------------------------------------
  465 /**
  466 * Creates the specified point cloud file. If the point cloud file already exists, it will be
  467 *  overwritten.
  468 * \param filename Complete path to point cloud file.
  469 * \param nvars Number of variables to save in the point cloud.
  470 * \param vartype A type for each variable. Types are the same as in the shading language:
  471 *           point, normal, color, float, matrix ... Etc.
  472 * \param varname A name for each variable.
  473 * \param world2eye A world to camera transformation matrix. (optional)
  474 * \param world2ndc A world to NDC transformation matrix. optional)
  475 * \param format The X resolution, Y resolution and aspect ratio of the image. (optional)
  476 */
  477 extern "C" PtcPointCloud PtcCreatePointCloudFile ( const char *filename, int nvars, const char **vartypes, const char **varnames, float *world2eye, float *world2ndc, float *format)
  478 {
  479     PtcPointCloudHandle *  ptc = new PtcPointCloudHandle;
  480     unsigned char exist;
  481     memset((void*)ptc, 0, sizeof(PtcPointCloudHandle));
  482     ptc->fp = fopen(filename, "wb");
  483 
  484     ptc->signature = PTCVERSION;
  485     strcpy(ptc->filename, filename);
  486     ptc->bbox[0] = FLT_MAX;
  487     ptc->bbox[2] = FLT_MAX;
  488     ptc->bbox[4] = FLT_MAX;
  489     ptc->bbox[1] = -FLT_MAX;
  490     ptc->bbox[3] = -FLT_MAX;
  491     ptc->bbox[5] = -FLT_MAX;
  492     int datasize = 0;
  493     fwrite(PTCNAME, 1, strlen(PTCNAME) + 1, ptc->fp);
  494     fwrite(&ptc->signature, 1, 1, ptc->fp);
  495     exist = nvars; // allow a maximum of 255 variables per ptc
  496     fwrite(&exist, 1, 1, ptc->fp);
  497     for (int i = 0; i < nvars; i++)
  498     {
  499         unsigned char size[2];
  500 
  501         size[0] = strlen(vartypes[i]) + 1;
  502         size[1] = strlen(varnames[i]) + 1;
  503         fwrite(size, 1, 2, ptc->fp);
  504 
  505         fwrite(vartypes[i], 1, size[0], ptc->fp);
  506         fwrite(varnames[i], 1, size[1], ptc->fp);
  507         if (strcmp(vartypes[i],"float") == 0) datasize ++;
  508         else if (strcmp(vartypes[i],"color") == 0) datasize += 3;
  509         else if (strcmp(vartypes[i],"normal") == 0) datasize += 3;
  510         else if (strcmp(vartypes[i],"vector") == 0) datasize += 3;
  511         else if (strcmp(vartypes[i],"point") == 0) datasize += 3;
  512         else if (strcmp(vartypes[i],"matrix") == 0) datasize += 16;
  513         else
  514         {
  515             // Not sure it should abort()!!!
  516             datasize ++;
  517         }
  518     }
  519     ptc->nvars = nvars;
  520     ptc->datasize = datasize;
  521     fwrite(&datasize, sizeof(int), 1, ptc->fp);
  522 
  523 
  524     if (world2eye != NULL)
  525     {
  526         exist = 1;
  527         fwrite(&exist, 1, 1, ptc->fp);
  528         fwrite(world2eye,sizeof(float), 16, ptc->fp);
  529     }
  530     else
  531     {
  532         exist = 0;
  533         fwrite(&exist, 1, 1, ptc->fp);
  534     }
  535 
  536     if (world2ndc != NULL)
  537     {
  538         exist = 1;
  539         fwrite(&exist, 1, 1, ptc->fp);
  540         fwrite(world2ndc,sizeof(float), 16, ptc->fp);
  541     }
  542     else
  543     {
  544         exist = 0;
  545         fwrite(&exist, 1, 1, ptc->fp);
  546     }
  547 
  548     if (format != NULL)
  549     {
  550         exist = 1;
  551         fwrite(&exist, 1, 1, ptc->fp);
  552         fwrite(&format, sizeof(float), 3, ptc->fp);
  553     }
  554     else
  555     {
  556         exist = 0;
  557         fwrite(&exist, 1, 1, ptc->fp);
  558     }
  559 
  560 
  561     return (PtcPointCloud)(ptc);
  562 }
  563 
  564 
  565 
  566 //---------------------------------------------------------------------
  567 /**
  568 *
  569 * Adds a point, along with its data, to a point cloud file.
  570 * \param pointcloud
  571 *             A handle to a point cloud file as returned by PtcCreatePointCloudFile.
  572 *        point normal radius Position, orientation and radius of the point and data. point and normal
  573 *        cannot be null.
  574 * \param data Array of floats containing data for all variables, continuously in memory.
  575 *            The data must be of the same size as the sum of sizes of the variables
  576 *        passed to PtcCreatePointCloudFile.
  577 * \return 1 if the operation is successful, 0 otherwise.
  578 */
  579 extern "C" int PtcWriteDataPoint ( PtcPointCloud pointcloud, float *point, float *normal, float radius, float *data)
  580 {
  581     int error = 0;
  582     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  583     if (!ptc || ptc->signature != PTCVERSION)
  584     {
  585         error = 1;
  586     }
  587     else
  588     {
  589         // update the bounding box
  590         ptc->bbox[0] = MIN(ptc->bbox[0], point[0]);
  591         ptc->bbox[1] = MAX(ptc->bbox[1], point[0]);
  592         ptc->bbox[2] = MIN(ptc->bbox[2], point[1]);
  593         ptc->bbox[3] = MAX(ptc->bbox[3], point[1]);
  594         ptc->bbox[4] = MIN(ptc->bbox[4], point[2]);
  595         ptc->bbox[5] = MAX(ptc->bbox[5], point[2]);
  596 
  597 
  598         if (ptc->maxpoints == 0)
  599         {
  600             ptc->maxpoints = 1024;
  601             ptc->key = (PtcPointCloudKey *) (malloc(ptc->maxpoints * sizeof(PtcPointCloudKey) ));
  602             for (int i =0; i < 1024; i++)
  603                 ptc->key[i].user_data = (float *) (malloc(ptc->datasize * sizeof(float) ));
  604         }
  605         else if (ptc->npoints >= ptc->maxpoints)
  606         {
  607             ptc->maxpoints += 1024;
  608             ptc->key = (PtcPointCloudKey *) (realloc(ptc->key, ptc->maxpoints * sizeof(PtcPointCloudKey) ));
  609             for (int i =ptc->npoints; i < ptc->maxpoints; i++)
  610                 ptc->key[i].user_data = (float *) (malloc(ptc->datasize * sizeof(float) ));
  611         }
  612 
  613         for (int i = 0; i < 3; i ++)
  614         {
  615             ptc->key[ptc->npoints].point[i] = point[i];
  616             ptc->key[ptc->npoints].normal[i] = normal[i];
  617         }
  618         ptc->key[ptc->npoints].radius = radius;
  619         for (int i = 0; i < ptc->datasize; i ++)
  620         {
  621             ptc->key[ptc->npoints].user_data[i] = data[i];
  622         }
  623         ptc->npoints ++;
  624     }
  625     return error;
  626 }
  627 
  628 
  629 //---------------------------------------------------------------------
  630 /**
  631 * Writes out all data to disk and closes the file.
  632 */
  633 extern "C" void PtcFinishPointCloudFile ( PtcPointCloud pointcloud)
  634 {
  635     int error = 0;
  636     PtcPointCloudHandle * ptc = (PtcPointCloudHandle *)(pointcloud);
  637     if (!ptc || ptc->signature != PTCVERSION)
  638     {
  639         error = 1;
  640     }
  641     else if (ptc->fp != NULL)
  642     {
  643         fwrite(&ptc->bbox, sizeof(float), 6, ptc->fp);
  644 
  645         fwrite(&ptc->npoints, sizeof(int), 1, ptc->fp);
  646 
  647         if (ptc->npoints)
  648         {
  649             for (int i = 0; i < ptc->npoints; i++)
  650             {
  651                 fwrite(ptc->key[i].point, sizeof(float), 3, ptc->fp);
  652                 fwrite(ptc->key[i].normal, sizeof(float), 3, ptc->fp);
  653                 fwrite(&ptc->key[i].radius, sizeof(float), 1, ptc->fp);
  654                 fwrite(ptc->key[i].user_data, sizeof(float), ptc->datasize, ptc->fp);
  655 
  656             }
  657         }
  658 
  659         PtcClosePointCloudFile(pointcloud);
  660     }
  661 }