00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #define PICOMODEL_C
00037
00038
00039 #include "picointernal.h"
00040
00041
00042
00043
00044
00045
00046 int PicoInit (void)
00047 {
00048
00049 return 1;
00050 }
00051
00055 void PicoShutdown (void)
00056 {
00057 }
00058
00062 int PicoError (void)
00063 {
00064 return 0;
00065 }
00066
00070 void PicoSetMallocFunc (void *(*func) (size_t))
00071 {
00072 if (func != NULL)
00073 _pico_ptr_malloc = func;
00074 }
00075
00079 void PicoSetFreeFunc (void(*func) (void*))
00080 {
00081 if (func != NULL)
00082 _pico_ptr_free = func;
00083 }
00084
00088 void PicoSetLoadFileFunc (void(*func) (char*, unsigned char**, int*))
00089 {
00090 if (func != NULL)
00091 _pico_ptr_load_file = func;
00092 }
00093
00097 void PicoSetFreeFileFunc (void(*func) (void*))
00098 {
00099 if (func != NULL)
00100 _pico_ptr_free_file = func;
00101 }
00102
00106 void PicoSetPrintFunc (void(*func) (int, const char*))
00107 {
00108 if (func != NULL)
00109 _pico_ptr_print = func;
00110 }
00111
00112 static picoModel_t *PicoModuleLoadModel (const picoModule_t* pm, const char* fileName, picoByte_t* buffer, int bufSize,
00113 int frameNum)
00114 {
00115
00116 if (pm->canload(fileName, buffer, bufSize) == PICO_PMV_OK) {
00117
00118 picoModel_t* model = pm->load(fileName, frameNum, buffer, bufSize);
00119 if (model == NULL) {
00120 _pico_free_file(buffer);
00121 return NULL;
00122 }
00123
00124
00125 model->module = pm;
00126
00127 return model;
00128 }
00129
00130 return NULL;
00131 }
00132
00136 picoModel_t *PicoLoadModel (char *fileName, int frameNum)
00137 {
00138 const picoModule_t **modules, *pm;
00139 picoModel_t *model;
00140 picoByte_t *buffer;
00141 int bufSize;
00142
00143
00144 model = NULL;
00145
00146
00147 if (fileName == NULL) {
00148 _pico_printf(PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)");
00149 return NULL;
00150 }
00151
00152
00153 _pico_load_file(fileName, &buffer, &bufSize);
00154 if (bufSize < 0) {
00155 _pico_printf(PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName);
00156 return NULL;
00157 }
00158
00159
00160 modules = PicoModuleList(NULL);
00161
00162
00163
00164 for (; *modules != NULL; modules++) {
00165
00166 pm = *modules;
00167
00168
00169 if (pm == NULL)
00170 break;
00171
00172
00173 if (pm->canload == NULL || pm->load == NULL)
00174 continue;
00175
00176 model = PicoModuleLoadModel(pm, fileName, buffer, bufSize, frameNum);
00177 if (model != NULL) {
00178
00179 break;
00180 }
00181 }
00182
00183
00184 if (buffer)
00185 _pico_free_file(buffer);
00186
00187
00188 return model;
00189 }
00190
00191 picoModel_t *PicoModuleLoadModelStream (const picoModule_t* module, const char *fileName, void* inputStream,
00192 PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum)
00193 {
00194 picoModel_t *model;
00195 picoByte_t *buffer;
00196 int bufSize;
00197
00198
00199 model = NULL;
00200
00201 if (inputStream == NULL) {
00202 _pico_printf(PICO_ERROR, "PicoLoadModel: invalid input stream (inputStream == NULL)");
00203 return NULL;
00204 }
00205
00206 if (inputStreamRead == NULL) {
00207 _pico_printf(PICO_ERROR, "PicoLoadModel: invalid input stream (inputStreamRead == NULL)");
00208 return NULL;
00209 }
00210
00211 buffer = _pico_alloc(streamLength + 1);
00212
00213 bufSize = (int) inputStreamRead(inputStream, buffer, streamLength);
00214 buffer[bufSize] = '\0';
00215
00216 model = PicoModuleLoadModel(module, fileName, buffer, bufSize, frameNum);
00217 if (model != 0)
00218 _pico_free(buffer);
00219
00220
00221 return model;
00222 }
00223
00227 picoModel_t *PicoNewModel (void)
00228 {
00229 picoModel_t *model;
00230
00231
00232 model = _pico_alloc(sizeof(picoModel_t));
00233 if (model == NULL)
00234 return NULL;
00235
00236
00237 memset(model, 0, sizeof(picoModel_t));
00238
00239
00240 _pico_zero_bounds(model->mins, model->maxs);
00241
00242
00243 model->numFrames = 1;
00244
00245
00246 return model;
00247 }
00248
00252 void PicoFreeModel (picoModel_t *model)
00253 {
00254 int i;
00255
00256
00257 if (model == NULL)
00258 return;
00259
00260
00261 if (model->name)
00262 _pico_free(model->name);
00263
00264 if (model->fileName)
00265 _pico_free(model->fileName);
00266
00267
00268 for (i = 0; i < model->numShaders; i++)
00269 PicoFreeShader(model->shader[i]);
00270 free(model->shader);
00271
00272
00273 for (i = 0; i < model->numSurfaces; i++)
00274 PicoFreeSurface(model->surface[i]);
00275 free(model->surface);
00276
00277
00278 _pico_free(model);
00279 }
00280
00285 int PicoAdjustModel (picoModel_t *model, int numShaders, int numSurfaces)
00286 {
00287
00288 if (model == NULL)
00289 return 0;
00290
00291
00292
00293 if (numShaders < 0)
00294 numShaders = 0;
00295 if (numSurfaces < 0)
00296 numSurfaces = 0;
00297
00298
00299 while (numShaders > model->maxShaders) {
00300 model->maxShaders += PICO_GROW_SHADERS;
00301 if (!_pico_realloc((void *) &model->shader, model->numShaders * sizeof(*model->shader), model->maxShaders
00302 * sizeof(*model->shader)))
00303 return 0;
00304 }
00305
00306
00307 if (numShaders > model->numShaders)
00308 model->numShaders = numShaders;
00309
00310
00311 while (numSurfaces > model->maxSurfaces) {
00312 model->maxSurfaces += PICO_GROW_SURFACES;
00313 if (!_pico_realloc((void *) &model->surface, model->numSurfaces * sizeof(*model->surface), model->maxSurfaces
00314 * sizeof(*model->surface)))
00315 return 0;
00316 }
00317
00318
00319 if (numSurfaces > model->numSurfaces)
00320 model->numSurfaces = numSurfaces;
00321
00322
00323 return 1;
00324 }
00325
00329 picoShader_t *PicoNewShader (picoModel_t *model)
00330 {
00331 picoShader_t *shader;
00332
00333
00334 shader = _pico_alloc(sizeof(*shader));
00335 if (shader == NULL)
00336 return NULL;
00337 memset(shader, 0, sizeof(*shader));
00338
00339
00340 if (model != NULL) {
00341
00342 if (!PicoAdjustModel(model, model->numShaders + 1, 0)) {
00343 _pico_free(shader);
00344 return NULL;
00345 }
00346
00347
00348 model->shader[model->numShaders - 1] = shader;
00349 shader->model = model;
00350 }
00351
00352
00353 _pico_set_color(shader->ambientColor, 0, 0, 0, 0);
00354 _pico_set_color(shader->diffuseColor, 255, 255, 255, 1);
00355 _pico_set_color(shader->specularColor, 0, 0, 0, 0);
00356
00357
00358 shader->transparency = 0;
00359 shader->shininess = 0;
00360
00361
00362 return shader;
00363 }
00364
00368 void PicoFreeShader (picoShader_t *shader)
00369 {
00370
00371 if (shader == NULL)
00372 return;
00373
00374
00375 if (shader->name)
00376 _pico_free(shader->name);
00377 if (shader->mapName)
00378 _pico_free(shader->mapName);
00379
00380
00381 _pico_free(shader);
00382 }
00383
00387 picoShader_t *PicoFindShader (picoModel_t *model, char *name, int caseSensitive)
00388 {
00389 int i;
00390
00391
00392 if (model == NULL || name == NULL)
00393 return NULL;
00394
00395
00396 for (i = 0; i < model->numShaders; i++) {
00397
00398 if (model->shader[i] == NULL || model->shader[i]->name == NULL)
00399 continue;
00400
00401
00402 if (caseSensitive) {
00403 if (!strcmp(name, model->shader[i]->name))
00404 return model->shader[i];
00405 } else if (!_pico_stricmp(name, model->shader[i]->name))
00406 return model->shader[i];
00407 }
00408
00409
00410 return NULL;
00411 }
00412
00416 picoSurface_t *PicoNewSurface (picoModel_t *model)
00417 {
00418 picoSurface_t *surface;
00419 char surfaceName[64];
00420
00421
00422 surface = _pico_alloc(sizeof(*surface));
00423 if (surface == NULL)
00424 return NULL;
00425 memset(surface, 0, sizeof(*surface));
00426
00427
00428 if (model != NULL) {
00429
00430 if (!PicoAdjustModel(model, 0, model->numSurfaces + 1)) {
00431 _pico_free(surface);
00432 return NULL;
00433 }
00434
00435
00436 model->surface[model->numSurfaces - 1] = surface;
00437 surface->model = model;
00438
00439
00440 sprintf(surfaceName, "Unnamed_%d", model->numSurfaces);
00441 PicoSetSurfaceName(surface, surfaceName);
00442 }
00443
00444
00445 return surface;
00446 }
00447
00451 void PicoFreeSurface (picoSurface_t *surface)
00452 {
00453 int i;
00454
00455
00456 if (surface == NULL)
00457 return;
00458
00459
00460 _pico_free(surface->xyz);
00461 _pico_free(surface->normal);
00462 _pico_free(surface->smoothingGroup);
00463 _pico_free(surface->index);
00464 _pico_free(surface->faceNormal);
00465
00466 if (surface->name)
00467 _pico_free(surface->name);
00468
00469
00470 for (i = 0; i < surface->numSTArrays; i++)
00471 _pico_free(surface->st[i]);
00472 free(surface->st);
00473 for (i = 0; i < surface->numColorArrays; i++)
00474 _pico_free(surface->color[i]);
00475 free(surface->color);
00476
00477
00478 _pico_free(surface);
00479 }
00480
00485 int PicoAdjustSurface (picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes,
00486 int numFaceNormals)
00487 {
00488 int i;
00489
00490
00491 if (surface == NULL)
00492 return 0;
00493
00494
00495 if (numVertexes < 1)
00496 numVertexes = 1;
00497 if (numSTArrays < 1)
00498 numSTArrays = 1;
00499 if (numColorArrays < 1)
00500 numColorArrays = 1;
00501 if (numIndexes < 1)
00502 numIndexes = 1;
00503
00504
00505 while (numVertexes > surface->maxVertexes) {
00506 surface->maxVertexes += PICO_GROW_VERTEXES;
00507 if (!_pico_realloc((void *) &surface->xyz, surface->numVertexes * sizeof(*surface->xyz), surface->maxVertexes
00508 * sizeof(*surface->xyz)))
00509 return 0;
00510 if (!_pico_realloc((void *) &surface->normal, surface->numVertexes * sizeof(*surface->normal),
00511 surface->maxVertexes * sizeof(*surface->normal)))
00512 return 0;
00513 if (!_pico_realloc((void *) &surface->smoothingGroup, surface->numVertexes * sizeof(*surface->smoothingGroup),
00514 surface->maxVertexes * sizeof(*surface->smoothingGroup)))
00515 return 0;
00516 for (i = 0; i < surface->numSTArrays; i++)
00517 if (!_pico_realloc((void*) &surface->st[i], surface->numVertexes * sizeof(*surface->st[i]),
00518 surface->maxVertexes * sizeof(*surface->st[i])))
00519 return 0;
00520 for (i = 0; i < surface->numColorArrays; i++)
00521 if (!_pico_realloc((void*) &surface->color[i], surface->numVertexes * sizeof(*surface->color[i]),
00522 surface->maxVertexes * sizeof(*surface->color[i])))
00523 return 0;
00524 }
00525
00526
00527 if (numVertexes > surface->numVertexes)
00528 surface->numVertexes = numVertexes;
00529
00530
00531 while (numSTArrays > surface->maxSTArrays) {
00532 surface->maxSTArrays += PICO_GROW_ARRAYS;
00533 if (!_pico_realloc((void*) &surface->st, surface->numSTArrays * sizeof(*surface->st), surface->maxSTArrays
00534 * sizeof(*surface->st)))
00535 return 0;
00536 while (surface->numSTArrays < numSTArrays) {
00537 surface->st[surface->numSTArrays] = _pico_alloc(surface->maxVertexes * sizeof(*surface->st[0]));
00538 memset(surface->st[surface->numSTArrays], 0, surface->maxVertexes * sizeof(*surface->st[0]));
00539 surface->numSTArrays++;
00540 }
00541 }
00542
00543
00544 while (numColorArrays > surface->maxColorArrays) {
00545 surface->maxColorArrays += PICO_GROW_ARRAYS;
00546 if (!_pico_realloc((void*) &surface->color, surface->numColorArrays * sizeof(*surface->color),
00547 surface->maxColorArrays * sizeof(*surface->color)))
00548 return 0;
00549 while (surface->numColorArrays < numColorArrays) {
00550 surface->color[surface->numColorArrays] = _pico_alloc(surface->maxVertexes * sizeof(*surface->color[0]));
00551 memset(surface->color[surface->numColorArrays], 0, surface->maxVertexes * sizeof(*surface->color[0]));
00552 surface->numColorArrays++;
00553 }
00554 }
00555
00556
00557 while (numIndexes > surface->maxIndexes) {
00558 surface->maxIndexes += PICO_GROW_INDEXES;
00559 if (!_pico_realloc((void*) &surface->index, surface->numIndexes * sizeof(*surface->index), surface->maxIndexes
00560 * sizeof(*surface->index)))
00561 return 0;
00562 }
00563
00564
00565 if (numIndexes > surface->numIndexes)
00566 surface->numIndexes = numIndexes;
00567
00568
00569 while (numFaceNormals > surface->maxFaceNormals) {
00570 surface->maxFaceNormals += PICO_GROW_FACES;
00571 if (!_pico_realloc((void *) &surface->faceNormal, surface->numFaceNormals * sizeof(*surface->faceNormal),
00572 surface->maxFaceNormals * sizeof(*surface->faceNormal)))
00573 return 0;
00574 }
00575
00576
00577 if (numFaceNormals > surface->numFaceNormals)
00578 surface->numFaceNormals = numFaceNormals;
00579
00580
00581 return 1;
00582 }
00583
00587 picoSurface_t *PicoFindSurface (picoModel_t *model, char *name, int caseSensitive)
00588 {
00589 int i;
00590
00591
00592 if (model == NULL || name == NULL)
00593 return NULL;
00594
00595
00596 for (i = 0; i < model->numSurfaces; i++) {
00597
00598 if (model->surface[i] == NULL || model->surface[i]->name == NULL)
00599 continue;
00600
00601
00602 if (caseSensitive) {
00603 if (!strcmp(name, model->surface[i]->name))
00604 return model->surface[i];
00605 } else {
00606 if (!_pico_stricmp(name, model->surface[i]->name))
00607 return model->surface[i];
00608 }
00609 }
00610
00611 return NULL;
00612 }
00613
00614 void PicoSetModelName (picoModel_t *model, const char *name)
00615 {
00616 if (model == NULL || name == NULL)
00617 return;
00618 if (model->name != NULL)
00619 _pico_free(model->name);
00620
00621 model->name = _pico_clone_alloc(name);
00622 }
00623
00624 void PicoSetModelFileName (picoModel_t *model, const char *fileName)
00625 {
00626 if (model == NULL || fileName == NULL)
00627 return;
00628 if (model->fileName != NULL)
00629 _pico_free(model->fileName);
00630
00631 model->fileName = _pico_clone_alloc(fileName);
00632 }
00633
00634 void PicoSetModelFrameNum (picoModel_t *model, int frameNum)
00635 {
00636 if (model == NULL)
00637 return;
00638 model->frameNum = frameNum;
00639 }
00640
00641 void PicoSetModelNumFrames (picoModel_t *model, int numFrames)
00642 {
00643 if (model == NULL)
00644 return;
00645 model->numFrames = numFrames;
00646 }
00647
00648 void PicoSetModelData (picoModel_t *model, void *data)
00649 {
00650 if (model == NULL)
00651 return;
00652 model->data = data;
00653 }
00654
00655 void PicoSetShaderName (picoShader_t *shader, const char *name)
00656 {
00657 if (shader == NULL || name == NULL)
00658 return;
00659 if (shader->name != NULL)
00660 _pico_free(shader->name);
00661
00662 shader->name = _pico_clone_alloc(name);
00663 }
00664
00665 void PicoSetShaderMapName (picoShader_t *shader, char *mapName)
00666 {
00667 if (shader == NULL || mapName == NULL)
00668 return;
00669 if (shader->mapName != NULL)
00670 _pico_free(shader->mapName);
00671
00672 shader->mapName = _pico_clone_alloc(mapName);
00673 }
00674
00675 void PicoSetShaderAmbientColor (picoShader_t *shader, picoColor_t color)
00676 {
00677 if (shader == NULL || color == NULL)
00678 return;
00679 shader->ambientColor[0] = color[0];
00680 shader->ambientColor[1] = color[1];
00681 shader->ambientColor[2] = color[2];
00682 shader->ambientColor[3] = color[3];
00683 }
00684
00685 void PicoSetShaderDiffuseColor (picoShader_t *shader, picoColor_t color)
00686 {
00687 if (shader == NULL || color == NULL)
00688 return;
00689 shader->diffuseColor[0] = color[0];
00690 shader->diffuseColor[1] = color[1];
00691 shader->diffuseColor[2] = color[2];
00692 shader->diffuseColor[3] = color[3];
00693 }
00694
00695 void PicoSetShaderSpecularColor (picoShader_t *shader, picoColor_t color)
00696 {
00697 if (shader == NULL || color == NULL)
00698 return;
00699 shader->specularColor[0] = color[0];
00700 shader->specularColor[1] = color[1];
00701 shader->specularColor[2] = color[2];
00702 shader->specularColor[3] = color[3];
00703 }
00704
00705 void PicoSetShaderTransparency (picoShader_t *shader, float value)
00706 {
00707 if (shader == NULL)
00708 return;
00709 shader->transparency = value;
00710
00711
00712 if (shader->transparency < 0.0)
00713 shader->transparency = 0.0;
00714 if (shader->transparency > 1.0)
00715 shader->transparency = 1.0;
00716 }
00717
00718 void PicoSetShaderShininess (picoShader_t *shader, float value)
00719 {
00720 if (shader == NULL)
00721 return;
00722 shader->shininess = value;
00723
00724
00725 if (shader->shininess < 0.0)
00726 shader->shininess = 0.0;
00727 if (shader->shininess > 127.0)
00728 shader->shininess = 127.0;
00729 }
00730
00731 void PicoSetSurfaceData (picoSurface_t *surface, void *data)
00732 {
00733 if (surface == NULL)
00734 return;
00735 surface->data = data;
00736 }
00737
00738 void PicoSetSurfaceType (picoSurface_t *surface, picoSurfaceType_t type)
00739 {
00740 if (surface == NULL)
00741 return;
00742 surface->type = type;
00743 }
00744
00745 void PicoSetSurfaceName (picoSurface_t *surface, char *name)
00746 {
00747 if (surface == NULL || name == NULL)
00748 return;
00749 if (surface->name != NULL)
00750 _pico_free(surface->name);
00751
00752 surface->name = _pico_clone_alloc(name);
00753 }
00754
00755 void PicoSetSurfaceShader (picoSurface_t *surface, picoShader_t *shader)
00756 {
00757 if (surface == NULL)
00758 return;
00759 surface->shader = shader;
00760 }
00761
00762 void PicoSetSurfaceXYZ (picoSurface_t *surface, int num, picoVec3_t xyz)
00763 {
00764 if (surface == NULL || num < 0 || xyz == NULL)
00765 return;
00766 if (!PicoAdjustSurface(surface, num + 1, 0, 0, 0, 0))
00767 return;
00768 _pico_copy_vec(xyz, surface->xyz[num]);
00769 if (surface->model != NULL)
00770 _pico_expand_bounds(xyz, surface->model->mins, surface->model->maxs);
00771 }
00772
00773 void PicoSetSurfaceNormal (picoSurface_t *surface, int num, picoVec3_t normal)
00774 {
00775 if (surface == NULL || num < 0 || normal == NULL)
00776 return;
00777 if (!PicoAdjustSurface(surface, num + 1, 0, 0, 0, 0))
00778 return;
00779 _pico_copy_vec(normal, surface->normal[num]);
00780 }
00781
00782 void PicoSetSurfaceST (picoSurface_t *surface, int array, int num, picoVec2_t st)
00783 {
00784 if (surface == NULL || num < 0 || st == NULL)
00785 return;
00786 if (!PicoAdjustSurface(surface, num + 1, array + 1, 0, 0, 0))
00787 return;
00788 surface->st[array][num][0] = st[0];
00789 surface->st[array][num][1] = st[1];
00790 }
00791
00792 void PicoSetSurfaceColor (picoSurface_t *surface, int array, int num, const picoColor_t color)
00793 {
00794 if (surface == NULL || num < 0 || color == NULL)
00795 return;
00796 if (!PicoAdjustSurface(surface, num + 1, 0, array + 1, 0, 0))
00797 return;
00798 surface->color[array][num][0] = color[0];
00799 surface->color[array][num][1] = color[1];
00800 surface->color[array][num][2] = color[2];
00801 surface->color[array][num][3] = color[3];
00802 }
00803
00804 void PicoSetSurfaceIndex (picoSurface_t *surface, int num, picoIndex_t index)
00805 {
00806 if (surface == NULL || num < 0)
00807 return;
00808 if (!PicoAdjustSurface(surface, 0, 0, 0, num + 1, 0))
00809 return;
00810 surface->index[num] = index;
00811 }
00812
00813 void PicoSetSurfaceIndexes (picoSurface_t *surface, int num, picoIndex_t *index, int count)
00814 {
00815 if (num < 0 || index == NULL || count < 1)
00816 return;
00817 if (!PicoAdjustSurface(surface, 0, 0, 0, num + count, 0))
00818 return;
00819 memcpy(&surface->index[num], index, count * sizeof(surface->index[num]));
00820 }
00821
00822 void PicoSetFaceNormal (picoSurface_t *surface, int num, picoVec3_t normal)
00823 {
00824 if (surface == NULL || num < 0 || normal == NULL)
00825 return;
00826 if (!PicoAdjustSurface(surface, 0, 0, 0, 0, num + 1))
00827 return;
00828 _pico_copy_vec(normal, surface->faceNormal[num]);
00829 }
00830
00831 void PicoSetSurfaceSmoothingGroup (picoSurface_t *surface, int num, picoIndex_t smoothingGroup)
00832 {
00833 if (num < 0)
00834 return;
00835 if (!PicoAdjustSurface(surface, num + 1, 0, 0, 0, 0))
00836 return;
00837 surface->smoothingGroup[num] = smoothingGroup;
00838 }
00839
00840 void PicoSetSurfaceSpecial (picoSurface_t *surface, int num, int special)
00841 {
00842 if (surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL)
00843 return;
00844 surface->special[num] = special;
00845 }
00846
00847 char *PicoGetModelName (picoModel_t *model)
00848 {
00849 if (model == NULL)
00850 return NULL;
00851 if (model->name == NULL)
00852 return (char*) "";
00853 return model->name;
00854 }
00855
00856 char *PicoGetModelFileName (picoModel_t *model)
00857 {
00858 if (model == NULL)
00859 return NULL;
00860 if (model->fileName == NULL)
00861 return (char*) "";
00862 return model->fileName;
00863 }
00864
00865 int PicoGetModelFrameNum (picoModel_t *model)
00866 {
00867 if (model == NULL)
00868 return 0;
00869 return model->frameNum;
00870 }
00871
00872 int PicoGetModelNumFrames (picoModel_t *model)
00873 {
00874 if (model == NULL)
00875 return 0;
00876 return model->numFrames;
00877 }
00878
00879 void *PicoGetModelData (picoModel_t *model)
00880 {
00881 if (model == NULL)
00882 return NULL;
00883 return model->data;
00884 }
00885
00886 int PicoGetModelNumShaders (picoModel_t *model)
00887 {
00888 if (model == NULL)
00889 return 0;
00890 return model->numShaders;
00891 }
00892
00893 picoShader_t *PicoGetModelShader (picoModel_t *model, int num)
00894 {
00895
00896 if (model == NULL)
00897 return NULL;
00898 if (model->shader == NULL)
00899 return NULL;
00900 if (num < 0 || num >= model->numShaders)
00901 return NULL;
00902
00903
00904 return model->shader[num];
00905 }
00906
00907 int PicoGetModelNumSurfaces (picoModel_t *model)
00908 {
00909 if (model == NULL)
00910 return 0;
00911 return model->numSurfaces;
00912 }
00913
00914 picoSurface_t *PicoGetModelSurface (picoModel_t *model, int num)
00915 {
00916
00917 if (model == NULL)
00918 return NULL;
00919 if (model->surface == NULL)
00920 return NULL;
00921 if (num < 0 || num >= model->numSurfaces)
00922 return NULL;
00923
00924
00925 return model->surface[num];
00926 }
00927
00928 int PicoGetModelTotalVertexes (picoModel_t *model)
00929 {
00930 int i, count;
00931
00932 if (model == NULL)
00933 return 0;
00934 if (model->surface == NULL)
00935 return 0;
00936
00937 count = 0;
00938 for (i = 0; i < model->numSurfaces; i++)
00939 count += PicoGetSurfaceNumVertexes(model->surface[i]);
00940
00941 return count;
00942 }
00943
00944 int PicoGetModelTotalIndexes (picoModel_t *model)
00945 {
00946 int i, count;
00947
00948 if (model == NULL)
00949 return 0;
00950 if (model->surface == NULL)
00951 return 0;
00952
00953 count = 0;
00954 for (i = 0; i < model->numSurfaces; i++)
00955 count += PicoGetSurfaceNumIndexes(model->surface[i]);
00956
00957 return count;
00958 }
00959
00960 char *PicoGetShaderName (picoShader_t *shader)
00961 {
00962 if (shader == NULL)
00963 return NULL;
00964 if (shader->name == NULL)
00965 return (char*) "";
00966 return shader->name;
00967 }
00968
00969 char *PicoGetShaderMapName (picoShader_t *shader)
00970 {
00971 if (shader == NULL)
00972 return NULL;
00973 if (shader->mapName == NULL)
00974 return (char*) "";
00975 return shader->mapName;
00976 }
00977
00978 picoByte_t *PicoGetShaderAmbientColor (picoShader_t *shader)
00979 {
00980 if (shader == NULL)
00981 return NULL;
00982 return shader->ambientColor;
00983 }
00984
00985 picoByte_t *PicoGetShaderDiffuseColor (picoShader_t *shader)
00986 {
00987 if (shader == NULL)
00988 return NULL;
00989 return shader->diffuseColor;
00990 }
00991
00992 picoByte_t *PicoGetShaderSpecularColor (picoShader_t *shader)
00993 {
00994 if (shader == NULL)
00995 return NULL;
00996 return shader->specularColor;
00997 }
00998
00999 float PicoGetShaderTransparency (picoShader_t *shader)
01000 {
01001 if (shader == NULL)
01002 return 0.0f;
01003 return shader->transparency;
01004 }
01005
01006 float PicoGetShaderShininess (picoShader_t *shader)
01007 {
01008 if (shader == NULL)
01009 return 0.0f;
01010 return shader->shininess;
01011 }
01012
01013 void *PicoGetSurfaceData (picoSurface_t *surface)
01014 {
01015 if (surface == NULL)
01016 return NULL;
01017 return surface->data;
01018 }
01019
01020 picoSurfaceType_t PicoGetSurfaceType (picoSurface_t *surface)
01021 {
01022 if (surface == NULL)
01023 return PICO_BAD;
01024 return surface->type;
01025 }
01026
01027 char *PicoGetSurfaceName (picoSurface_t *surface)
01028 {
01029 if (surface == NULL)
01030 return NULL;
01031 if (surface->name == NULL)
01032 return (char*) "";
01033 return surface->name;
01034 }
01035
01036 picoShader_t *PicoGetSurfaceShader (picoSurface_t *surface)
01037 {
01038 if (surface == NULL)
01039 return NULL;
01040 return surface->shader;
01041 }
01042
01043 int PicoGetSurfaceNumVertexes (picoSurface_t *surface)
01044 {
01045 if (surface == NULL)
01046 return 0;
01047 return surface->numVertexes;
01048 }
01049
01050 picoVec_t *PicoGetSurfaceXYZ (picoSurface_t *surface, int num)
01051 {
01052 if (surface == NULL || num < 0 || num > surface->numVertexes)
01053 return NULL;
01054 return surface->xyz[num];
01055 }
01056
01057 picoVec_t *PicoGetSurfaceNormal (picoSurface_t *surface, int num)
01058 {
01059 if (surface == NULL || num < 0 || num > surface->numVertexes)
01060 return NULL;
01061 return surface->normal[num];
01062 }
01063
01064 picoVec_t *PicoGetSurfaceST (picoSurface_t *surface, int array, int num)
01065 {
01066 if (surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes)
01067 return NULL;
01068 return surface->st[array][num];
01069 }
01070
01071 picoByte_t *PicoGetSurfaceColor (picoSurface_t *surface, int array, int num)
01072 {
01073 if (surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes)
01074 return NULL;
01075 return surface->color[array][num];
01076 }
01077
01078 int PicoGetSurfaceNumIndexes (picoSurface_t *surface)
01079 {
01080 if (surface == NULL)
01081 return 0;
01082 return surface->numIndexes;
01083 }
01084
01085 picoIndex_t PicoGetSurfaceIndex (picoSurface_t *surface, int num)
01086 {
01087 if (surface == NULL || num < 0 || num > surface->numIndexes)
01088 return 0;
01089 return surface->index[num];
01090 }
01091
01092 picoIndex_t *PicoGetSurfaceIndexes (picoSurface_t *surface, int num)
01093 {
01094 if (surface == NULL || num < 0 || num > surface->numIndexes)
01095 return NULL;
01096 return &surface->index[num];
01097 }
01098
01099 picoVec_t *PicoGetFaceNormal (picoSurface_t *surface, int num)
01100 {
01101 if (surface == NULL || num < 0 || num > surface->numFaceNormals)
01102 return NULL;
01103 return surface->faceNormal[num];
01104 }
01105
01106 int PicoGetSurfaceSpecial (picoSurface_t *surface, int num)
01107 {
01108 if (surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL)
01109 return 0;
01110 return surface->special[num];
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 #define HASHTABLE_SIZE 7919
01122 #define HASH_XYZ_EPSILON 0.01f
01123 #define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON
01124 #define HASH_ST_EPSILON 0.0001f
01125 #define HASH_NORMAL_EPSILON 0.02f
01126
01127 unsigned int PicoVertexCoordGenerateHash (picoVec3_t xyz)
01128 {
01129 unsigned int hash = 0;
01130
01131 picoVec3_t xyz_epsilonspace;
01132
01133 _pico_scale_vec(xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace);
01134 xyz_epsilonspace[0] = (float) floor(xyz_epsilonspace[0]);
01135 xyz_epsilonspace[1] = (float) floor(xyz_epsilonspace[1]);
01136 xyz_epsilonspace[2] = (float) floor(xyz_epsilonspace[2]);
01137
01138 hash += ~(*((unsigned int*) &xyz_epsilonspace[0]) << 15);
01139 hash ^= (*((unsigned int*) &xyz_epsilonspace[0]) >> 10);
01140 hash += (*((unsigned int*) &xyz_epsilonspace[1]) << 3);
01141 hash ^= (*((unsigned int*) &xyz_epsilonspace[1]) >> 6);
01142 hash += ~(*((unsigned int*) &xyz_epsilonspace[2]) << 11);
01143 hash ^= (*((unsigned int*) &xyz_epsilonspace[2]) >> 16);
01144
01145
01146 hash = hash % (HASHTABLE_SIZE);
01147 return hash;
01148 }
01149
01150 picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable (void)
01151 {
01152 picoVertexCombinationHash_t **hashTable = _pico_alloc(HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*));
01153
01154 memset(hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*));
01155
01156 return hashTable;
01157 }
01158
01159 void PicoFreeVertexCombinationHashTable (picoVertexCombinationHash_t **hashTable)
01160 {
01161 int i;
01162 picoVertexCombinationHash_t *vertexCombinationHash;
01163 picoVertexCombinationHash_t *nextVertexCombinationHash;
01164
01165
01166 if (hashTable == NULL)
01167 return;
01168
01169 for (i = 0; i < HASHTABLE_SIZE; i++) {
01170 if (hashTable[i]) {
01171 nextVertexCombinationHash = NULL;
01172
01173 for (vertexCombinationHash = hashTable[i]; vertexCombinationHash; vertexCombinationHash
01174 = nextVertexCombinationHash) {
01175 nextVertexCombinationHash = vertexCombinationHash->next;
01176 if (vertexCombinationHash->data != NULL) {
01177 _pico_free(vertexCombinationHash->data);
01178 }
01179 _pico_free(vertexCombinationHash);
01180 }
01181 }
01182 }
01183
01184 _pico_free(hashTable);
01185 }
01186
01187 picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable (picoVertexCombinationHash_t **hashTable,
01188 picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color)
01189 {
01190 unsigned int hash;
01191 picoVertexCombinationHash_t *vertexCombinationHash;
01192
01193
01194 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL)
01195 return NULL;
01196
01197 hash = PicoVertexCoordGenerateHash(xyz);
01198
01199 for (vertexCombinationHash = hashTable[hash]; vertexCombinationHash; vertexCombinationHash
01200 = vertexCombinationHash->next) {
01201
01202 if ((fabs(xyz[0] - vertexCombinationHash->vcd.xyz[0])) > HASH_XYZ_EPSILON || (fabs(xyz[1]
01203 - vertexCombinationHash->vcd.xyz[1])) > HASH_XYZ_EPSILON || (fabs(xyz[2]
01204 - vertexCombinationHash->vcd.xyz[2])) > HASH_XYZ_EPSILON)
01205 continue;
01206
01207
01208 if ((fabs(normal[0] - vertexCombinationHash->vcd.normal[0])) > HASH_NORMAL_EPSILON || (fabs(normal[1]
01209 - vertexCombinationHash->vcd.normal[1])) > HASH_NORMAL_EPSILON || (fabs(normal[2]
01210 - vertexCombinationHash->vcd.normal[2])) > HASH_NORMAL_EPSILON)
01211 continue;
01212
01213
01214 if ((fabs(st[0] - vertexCombinationHash->vcd.st[0])) > HASH_ST_EPSILON || (fabs(st[1]
01215 - vertexCombinationHash->vcd.st[1])) > HASH_ST_EPSILON)
01216 continue;
01217
01218
01219 if (*((int*) vertexCombinationHash->vcd.color) != *((int*) color))
01220 continue;
01221
01222
01223 return vertexCombinationHash;
01224 }
01225
01226 return NULL;
01227 }
01228
01229 picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable (picoVertexCombinationHash_t **hashTable,
01230 picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index)
01231 {
01232 unsigned int hash;
01233 picoVertexCombinationHash_t *vertexCombinationHash;
01234
01235
01236 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL)
01237 return NULL;
01238
01239 vertexCombinationHash = _pico_alloc(sizeof(picoVertexCombinationHash_t));
01240
01241 if (!vertexCombinationHash)
01242 return NULL;
01243
01244 hash = PicoVertexCoordGenerateHash(xyz);
01245
01246 _pico_copy_vec(xyz, vertexCombinationHash->vcd.xyz);
01247 _pico_copy_vec(normal, vertexCombinationHash->vcd.normal);
01248 _pico_copy_vec2(st, vertexCombinationHash->vcd.st);
01249 _pico_copy_color(color, vertexCombinationHash->vcd.color);
01250 vertexCombinationHash->index = index;
01251 vertexCombinationHash->data = NULL;
01252 vertexCombinationHash->next = hashTable[hash];
01253 hashTable[hash] = vertexCombinationHash;
01254
01255 return vertexCombinationHash;
01256 }
01257
01262 int PicoFindSurfaceVertexNum (picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st,
01263 int numColors, picoColor_t *color, picoIndex_t smoothingGroup)
01264 {
01265 int i, j;
01266
01267
01268 if (surface == NULL || surface->numVertexes <= 0)
01269 return -1;
01270
01271
01272 for (i = 0; i < surface->numVertexes; i++) {
01273
01274 if (xyz != NULL && (surface->xyz[i][0] != xyz[0] || surface->xyz[i][1] != xyz[1] || surface->xyz[i][2]
01275 != xyz[2]))
01276 continue;
01277
01278
01279 if (normal != NULL && (surface->normal[i][0] != normal[0] || surface->normal[i][1] != normal[1]
01280 || surface->normal[i][2] != normal[2]))
01281 continue;
01282
01283
01284 if (surface->smoothingGroup[i] != smoothingGroup)
01285 continue;
01286
01287
01288 if (numSTs > 0 && st != NULL) {
01289 for (j = 0; j < numSTs; j++) {
01290 if (surface->st[j][i][0] != st[j][0] || surface->st[j][i][1] != st[j][1])
01291 break;
01292 }
01293 if (j != numSTs)
01294 continue;
01295 }
01296
01297
01298 if (numColors > 0 && color != NULL) {
01299 for (j = 0; j < numSTs; j++) {
01300 if (*((int*) surface->color[j]) != *((int*) color[j]))
01301 break;
01302 }
01303 if (j != numColors)
01304 continue;
01305 }
01306
01307
01308 return i;
01309 }
01310
01311
01312 return -1;
01313 }
01314
01315 typedef struct _IndexArray
01316 {
01317 picoIndex_t* data;
01318 picoIndex_t* last;
01319 } IndexArray;
01320
01321 static void indexarray_push_back (IndexArray* self, picoIndex_t value)
01322 {
01323 *self->last++ = value;
01324 }
01325
01326 static void indexarray_reserve (IndexArray* self, size_t size)
01327 {
01328 self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t));
01329 }
01330
01331 static void indexarray_clear (IndexArray* self)
01332 {
01333 _pico_free(self->data);
01334 }
01335
01336 typedef struct _BinaryTreeNode
01337 {
01338 picoIndex_t left;
01339 picoIndex_t right;
01340 } BinaryTreeNode;
01341
01342 typedef struct _BinaryTree
01343 {
01344 BinaryTreeNode* data;
01345 BinaryTreeNode* last;
01346 } BinaryTree;
01347
01348 static void binarytree_extend (BinaryTree* self)
01349 {
01350 self->last->left = 0;
01351 self->last->right = 0;
01352 ++self->last;
01353 }
01354
01355 static size_t binarytree_size (BinaryTree* self)
01356 {
01357 return self->last - self->data;
01358 }
01359
01360 static void binarytree_reserve (BinaryTree* self, size_t size)
01361 {
01362 self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode));
01363 }
01364
01365 static void binarytree_clear (BinaryTree* self)
01366 {
01367 _pico_free(self->data);
01368 }
01369
01370 typedef int (*LessFunc) (void*, picoIndex_t, picoIndex_t);
01371
01372 typedef struct _UniqueIndices
01373 {
01374 BinaryTree tree;
01375 IndexArray indices;
01376 LessFunc lessFunc;
01377 void* lessData;
01378 } UniqueIndices;
01379
01380 static size_t UniqueIndices_size (UniqueIndices* self)
01381 {
01382 return binarytree_size(&self->tree);
01383 }
01384
01385 static void UniqueIndices_reserve (UniqueIndices* self, size_t size)
01386 {
01387 binarytree_reserve(&self->tree, size);
01388 indexarray_reserve(&self->indices, size);
01389 }
01390
01391 static void UniqueIndices_init (UniqueIndices* self, LessFunc lessFunc, void* lessData)
01392 {
01393 self->lessFunc = lessFunc;
01394 self->lessData = lessData;
01395 }
01396
01397 static void UniqueIndices_destroy (UniqueIndices* self)
01398 {
01399 binarytree_clear(&self->tree);
01400 indexarray_clear(&self->indices);
01401 }
01402
01403 static picoIndex_t UniqueIndices_find_or_insert (UniqueIndices* self, picoIndex_t value)
01404 {
01405 picoIndex_t index = 0;
01406
01407 for (;;) {
01408 if (self->lessFunc(self->lessData, value, self->indices.data[index])) {
01409 BinaryTreeNode* node = self->tree.data + index;
01410 if (node->left != 0) {
01411 index = node->left;
01412 continue;
01413 } else {
01414 node->left = (picoIndex_t) binarytree_size(&self->tree);
01415 binarytree_extend(&self->tree);
01416 indexarray_push_back(&self->indices, value);
01417 return node->left;
01418 }
01419 }
01420 if (self->lessFunc(self->lessData, self->indices.data[index], value)) {
01421 BinaryTreeNode* node = self->tree.data + index;
01422 if (node->right != 0) {
01423 index = node->right;
01424 continue;
01425 } else {
01426 node->right = (picoIndex_t) binarytree_size(&self->tree);
01427 binarytree_extend(&self->tree);
01428 indexarray_push_back(&self->indices, value);
01429 return node->right;
01430 }
01431 }
01432
01433 return index;
01434 }
01435 }
01436
01437 static picoIndex_t UniqueIndices_insert (UniqueIndices* self, picoIndex_t value)
01438 {
01439 if (self->tree.data == self->tree.last) {
01440 binarytree_extend(&self->tree);
01441 indexarray_push_back(&self->indices, value);
01442 return 0;
01443 } else {
01444 return UniqueIndices_find_or_insert(self, value);
01445 }
01446 }
01447
01448 typedef struct picoSmoothVertices_s
01449 {
01450 picoVec3_t* xyz;
01451 picoIndex_t* smoothingGroups;
01452 } picoSmoothVertices_t;
01453
01454 static int lessSmoothVertex (void* data, picoIndex_t first, picoIndex_t second)
01455 {
01456 picoSmoothVertices_t* smoothVertices = data;
01457
01458 if (smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0])
01459 return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
01460 if (smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1])
01461 return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
01462 if (smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2])
01463 return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
01464 if (smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second])
01465 return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
01466 return 0;
01467 }
01468
01469 static void _pico_vertices_combine_shared_normals (picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals,
01470 picoIndex_t numVertices)
01471 {
01472 UniqueIndices vertices;
01473 IndexArray indices;
01474 picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
01475 UniqueIndices_init(&vertices, lessSmoothVertex, &smoothVertices);
01476 UniqueIndices_reserve(&vertices, numVertices);
01477 indexarray_reserve(&indices, numVertices);
01478
01479 {
01480 picoIndex_t i = 0;
01481 for (; i < numVertices; ++i) {
01482 size_t size = UniqueIndices_size(&vertices);
01483 picoIndex_t index = UniqueIndices_insert(&vertices, i);
01484 if ((size_t) index != size) {
01485 float* normal = normals[vertices.indices.data[index]];
01486 _pico_add_vec(normal, normals[i], normal);
01487 }
01488 indexarray_push_back(&indices, index);
01489 }
01490 }
01491
01492 {
01493 picoIndex_t maxIndex = 0;
01494 picoIndex_t* i = indices.data;
01495 for (; i != indices.last; ++i) {
01496 if (*i <= maxIndex) {
01497 _pico_copy_vec(normals[vertices.indices.data[*i]], normals[i - indices.data]);
01498 } else {
01499 maxIndex = *i;
01500 }
01501 }
01502 }
01503
01504 UniqueIndices_destroy(&vertices);
01505 indexarray_clear(&indices);
01506 }
01507
01508 typedef picoVec3_t* picoNormalIter_t;
01509 typedef picoIndex_t* picoIndexIter_t;
01510
01511 static void _pico_triangles_generate_weighted_normals (picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz,
01512 picoVec3_t* normals)
01513 {
01514 for (; first != end; first += 3) {
01515 picoVec3_t weightedNormal;
01516 {
01517 float* a = xyz[*(first + 0)];
01518 float* b = xyz[*(first + 1)];
01519 float* c = xyz[*(first + 2)];
01520 picoVec3_t ba, ca;
01521 _pico_subtract_vec(b, a, ba);
01522 _pico_subtract_vec(c, a, ca);
01523 _pico_cross_vec(ca, ba, weightedNormal);
01524 }
01525 {
01526 int j = 0;
01527 for (; j < 3; ++j) {
01528 float* normal = normals[*(first + j)];
01529 _pico_add_vec(weightedNormal, normal, normal);
01530 }
01531 }
01532 }
01533 }
01534
01535 static void _pico_normals_zero (picoNormalIter_t first, picoNormalIter_t last)
01536 {
01537 for (; first != last; ++first) {
01538 _pico_zero_vec(*first);
01539 }
01540 }
01541
01542 static void _pico_normals_normalize (picoNormalIter_t first, picoNormalIter_t last)
01543 {
01544 for (; first != last; ++first) {
01545 _pico_normalize_vec(*first);
01546 }
01547 }
01548
01549 static double _pico_length_vec (picoVec3_t vec)
01550 {
01551 return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
01552 }
01553
01554 #define NORMAL_UNIT_LENGTH_EPSILON 0.01
01555 #define FLOAT_EQUAL_EPSILON(f, other, epsilon) (fabs(f - other) < epsilon)
01556
01557 static int _pico_normal_is_unit_length (picoVec3_t normal)
01558 {
01559 return FLOAT_EQUAL_EPSILON(_pico_length_vec(normal), 1.0, NORMAL_UNIT_LENGTH_EPSILON);
01560 }
01561
01562 static int _pico_normal_within_tolerance (picoVec3_t normal, picoVec3_t other)
01563 {
01564 return _pico_dot_vec(normal, other) > 0.0f;
01565 }
01566
01567 static void _pico_normals_assign_generated_normals (picoNormalIter_t first, picoNormalIter_t last,
01568 picoNormalIter_t generated)
01569 {
01570 for (; first != last; ++first, ++generated) {
01571 if (!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated)) {
01572 _pico_copy_vec(*generated, *first);
01573 }
01574 }
01575 }
01576
01577 void PicoFixSurfaceNormals (picoSurface_t* surface)
01578 {
01579 picoVec3_t* normals = (picoVec3_t*) _pico_calloc(surface->numVertexes, sizeof(picoVec3_t));
01580
01581 _pico_normals_zero(normals, normals + surface->numVertexes);
01582
01583 _pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz,
01584 normals);
01585 _pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
01586
01587 _pico_normals_normalize(normals, normals + surface->numVertexes);
01588
01589 _pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
01590
01591 _pico_free(normals);
01592 }
01593
01598 void PicoAddTriangleToModel (picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st,
01599 int numColors, picoColor_t **colors, picoShader_t* shader, picoIndex_t* smoothingGroup)
01600 {
01601 int i, j;
01602 int vertDataIndex;
01603 picoSurface_t* workSurface = NULL;
01604
01605
01606 for (i = 0; i < model->numSurfaces; i++) {
01607 workSurface = model->surface[i];
01608 if (workSurface->shader == shader) {
01609 break;
01610 }
01611 }
01612
01613
01614 if (!workSurface || i >= model->numSurfaces) {
01615
01616 workSurface = PicoNewSurface(model);
01617 if (!workSurface) {
01618 _pico_printf(PICO_ERROR, "Could not allocate a new surface!\n");
01619 return;
01620 }
01621
01622
01623 PicoSetSurfaceType(workSurface, PICO_TRIANGLES);
01624 PicoSetSurfaceName(workSurface, shader->name);
01625 PicoSetSurfaceShader(workSurface, shader);
01626 }
01627
01628
01629 for (i = 0; i < 3; i++) {
01630
01631 int newVertIndex = PicoGetSurfaceNumIndexes(workSurface);
01632
01633
01634 vertDataIndex = PicoFindSurfaceVertexNum(workSurface, *xyz[i], *normals[i], numSTs, st[i], numColors,
01635 colors[i], smoothingGroup[i]);
01636
01637
01638 if (vertDataIndex == -1) {
01639
01640 vertDataIndex = PicoGetSurfaceNumVertexes(workSurface);
01641
01642
01643 PicoSetSurfaceXYZ(workSurface, vertDataIndex, *xyz[i]);
01644 PicoSetSurfaceNormal(workSurface, vertDataIndex, *normals[i]);
01645
01646
01647 for (j = 0; j < numColors; j++) {
01648 PicoSetSurfaceColor(workSurface, j, vertDataIndex, colors[i][j]);
01649 }
01650 for (j = 0; j < numSTs; j++) {
01651 PicoSetSurfaceST(workSurface, j, vertDataIndex, st[i][j]);
01652 }
01653
01654 PicoSetSurfaceSmoothingGroup(workSurface, vertDataIndex, smoothingGroup[i]);
01655 }
01656
01657
01658 PicoSetSurfaceIndex(workSurface, newVertIndex, vertDataIndex);
01659 }
01660 }