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 #include "mmsgui/3d/mms3dpolygonmesh.h"
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <math.h>
00037
00038
00039 MMS3DPolygonMesh::MMS3DPolygonMesh() {
00040
00041
00042 this->pm_items_cnt = 0;
00043
00044
00045 this->varrays_cnt = 0;
00046 this->varrays[varrays_cnt] = NULL;
00047 this->iarrays_cnt = 0;
00048 this->iarrays[iarrays_cnt] = NULL;
00049 }
00050
00051 void MMS3DPolygonMesh::genRectangle(float width, float height,
00052 MMS_VERTEX_ARRAY *vertices,
00053 MMS_VERTEX_ARRAY *normals,
00054 MMS_VERTEX_ARRAY *texcoords,
00055 MMS_INDEX_ARRAY *indices) {
00056
00057
00058 initVertexArray(vertices, 2, 4);
00059 initVertexArray(normals, 3, 4);
00060 initVertexArray(texcoords, 2, 4);
00061
00062
00063 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
00064
00065
00066 MMS_VA_SET_VERTEX_2v(vertices, 0, -width/2, -height/2);
00067 MMS_VA_SET_VERTEX_2v(vertices, 1, width/2, -height/2);
00068 MMS_VA_SET_VERTEX_2v(vertices, 2, -width/2, height/2);
00069 MMS_VA_SET_VERTEX_2v(vertices, 3, width/2, height/2);
00070
00071
00072 MMS_VA_SET_VERTEX_3v(normals, 0, 0, 0, 1);
00073 MMS_VA_SET_VERTEX_3v(normals, 1, 0, 0, 1);
00074 MMS_VA_SET_VERTEX_3v(normals, 2, 0, 0, 1);
00075 MMS_VA_SET_VERTEX_3v(normals, 3, 0, 0, 1);
00076
00077
00078 MMS_VA_SET_VERTEX_2v(texcoords, 0, 0, 0);
00079 MMS_VA_SET_VERTEX_2v(texcoords, 1, 1, 0);
00080 MMS_VA_SET_VERTEX_2v(texcoords, 2, 0, 1);
00081 MMS_VA_SET_VERTEX_2v(texcoords, 3, 1, 1);
00082 }
00083
00084 void MMS3DPolygonMesh::genSphere(int numSlices, float radius,
00085 MMS_VERTEX_ARRAY *vertices,
00086 MMS_VERTEX_ARRAY *normals,
00087 MMS_VERTEX_ARRAY *texcoords,
00088 MMS_INDEX_ARRAY *indices) {
00089 int i;
00090 int j;
00091 int numParallels = numSlices / 2;
00092 float angleStep = (2.0f * MMS_PI) / ((float) numSlices);
00093
00094
00095 initVertexArray(vertices, 3, (numParallels + 1) * (numSlices + 1));
00096 initVertexArray(normals, 3, (numParallels + 1) * (numSlices + 1));
00097 initVertexArray(texcoords, 2, (numParallels + 1) * (numSlices + 1));
00098 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES, numParallels * numSlices * 6);
00099
00100 for ( i = 0; i < numParallels + 1; i++ ) {
00101 for ( j = 0; j < numSlices + 1; j++ ) {
00102 int v = ( i * (numSlices + 1) + j );
00103
00104
00105 MMS_VA_SET_VERTEX_3v(vertices, v,
00106 radius * sinf ( angleStep * (float)i ) * sinf ( angleStep * (float)j ),
00107 radius * cosf ( angleStep * (float)i ),
00108 radius * sinf ( angleStep * (float)i ) * cosf ( angleStep * (float)j ));
00109
00110
00111 if (vertices) {
00112 float *vdata = (float *)vertices->data;
00113 MMS_VA_SET_VERTEX_3v(normals, v,
00114 vdata[v * vertices->eSize + 0] / radius,
00115 vdata[v * vertices->eSize + 1] / radius,
00116 vdata[v * vertices->eSize + 2] / radius);
00117 }
00118
00119
00120 MMS_VA_SET_VERTEX_2v(texcoords, v,
00121 (float) j / (float) numSlices,
00122 ( 1.0f - (float) i ) / (float) (numParallels - 1 ));
00123 }
00124 }
00125
00126
00127 if (indices) {
00128 unsigned int *idata = (unsigned int *)indices->data;
00129 for ( i = 0; i < numParallels ; i++) {
00130 for ( j = 0; j < numSlices; j++) {
00131 *idata++ = i * ( numSlices + 1 ) + j;
00132 *idata++ = ( i + 1 ) * ( numSlices + 1 ) + j;
00133 *idata++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
00134 *idata++ = i * ( numSlices + 1 ) + j;
00135 *idata++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
00136 *idata++ = i * ( numSlices + 1 ) + ( j + 1 );
00137 }
00138 }
00139 }
00140 }
00141
00142 void MMS3DPolygonMesh::genTorus(int numwraps, int numperwrap, float majorradius, float minorradius,
00143 MMS_VERTEX_ARRAY *vertices,
00144 MMS_VERTEX_ARRAY *normals,
00145 MMS_VERTEX_ARRAY *texcoords,
00146 MMS_INDEX_ARRAY *indices) {
00147
00148
00149
00150 int eNum = (numwraps * numperwrap + 1) * 2;
00151
00152
00153 initVertexArray(vertices, 3, eNum);
00154 initVertexArray(normals, 3, eNum);
00155 initVertexArray(texcoords, 2, eNum);
00156
00157
00158 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
00159
00160
00161 int index = 0;
00162
00163
00164 float PI2 = 2.0f * MMS_PI;
00165 bool final = false;
00166 while (1) {
00167 for (int i = 0; i < numwraps; i++) {
00168 for (int j = 0; j < numperwrap; j++) {
00169
00170 float wrapFrac = (j % numperwrap) / (float)numperwrap;
00171 float phi = PI2*wrapFrac;
00172 float sinphi = sin(phi);
00173 float cosphi = cos(phi);
00174 float y = minorradius * sinphi;
00175 float r = majorradius + minorradius * cosphi;
00176
00177 for (int k = i; k <= i + 1; k++) {
00178
00179 float theta = PI2 * (k % numwraps+wrapFrac) / (float)numwraps;
00180 float sintheta = sin(theta);
00181 float costheta = cos(theta);
00182 float x = sintheta * r;
00183 float z = costheta * r;
00184
00185
00186 MMS_VA_SET_VERTEX_3v(normals, index,
00187 sintheta * cosphi,
00188 sinphi,
00189 costheta * cosphi);
00190
00191
00192 MMS_VA_SET_VERTEX_3v(vertices, index, x, y, z);
00193
00194 index++;
00195 }
00196
00197 if (final) break;
00198 }
00199 if (final) break;
00200 }
00201 if (final) break;
00202 final = true;
00203 }
00204 }
00205
00206 void MMS3DPolygonMesh::genCylinder(int numSlices, float height, float radius,
00207 MMS_VERTEX_ARRAY *vertices,
00208 MMS_VERTEX_ARRAY *normals,
00209 MMS_VERTEX_ARRAY *texcoords,
00210 MMS_INDEX_ARRAY *indices) {
00211
00212
00213
00214 int eNum = (numSlices + 1) * 2;
00215
00216
00217 initVertexArray(vertices, 3, eNum);
00218 initVertexArray(normals, 3, eNum);
00219 initVertexArray(texcoords, 2, eNum);
00220
00221
00222 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
00223
00224
00225 int index = 0;
00226
00227
00228 float angleStep = 2.0f * MMS_PI / ((float) numSlices);
00229 float z0 = 0.5 * height;
00230 float z1 = z0 - height;
00231
00232 for (int j = 0; j <= numSlices; j++) {
00233 float a = j * angleStep;
00234 float x = radius * cos(a);
00235 float y = radius * sin(a);
00236
00237
00238 MMS_VA_SET_VERTEX_3v(normals, index, x / radius, y / radius, 0);
00239 MMS_VA_SET_VERTEX_3v(normals, index+1, x / radius, y / radius, 0);
00240
00241
00242 MMS_VA_SET_VERTEX_3v(vertices, index, x, y, z0);
00243 MMS_VA_SET_VERTEX_3v(vertices, index+1, x, y, z1);
00244
00245
00246 MMS_VA_SET_VERTEX_2v(texcoords, index, j / (float) numSlices, 0);
00247 MMS_VA_SET_VERTEX_2v(texcoords, index+1, j / (float) numSlices, 1);
00248
00249 index+=2;
00250 }
00251 }
00252
00253 int MMS3DPolygonMesh::findPMItem(MMS3DPM_TYPE type, MMS3DPM_MESHID identifier, int *vertices, int *normals, int *texcoords, int *indices) {
00254 for (int i = 0; i < this->pm_items_cnt; i++) {
00255 MMS3DPM_ITEM *item = &this->pm_items[i];
00256
00257 if (item->type != type)
00258 continue;
00259 if (memcmp(item->identifier, identifier, sizeof(identifier)))
00260 continue;
00261 if (vertices && item->vertices < 0)
00262 continue;
00263 if (normals && item->normals < 0)
00264 continue;
00265 if (texcoords && item->texcoords < 0)
00266 continue;
00267 if (indices && item->indices < 0)
00268 continue;
00269
00270
00271 if (vertices) *vertices = item->vertices;
00272 if (normals) *normals = item->normals;
00273 if (texcoords)*texcoords = item->texcoords;
00274 if (indices) *indices = item->indices;
00275
00276 return i;
00277 }
00278
00279 return -1;
00280 }
00281
00282 int MMS3DPolygonMesh::newPMItem(MMS3DPM_TYPE type, MMS3DPM_MESHID identifier, int *vertices, int *normals, int *texcoords, int *indices) {
00283 if (this->pm_items_cnt >= MMS3DPM_ITEM_MAX) {
00284
00285 return -1;
00286 }
00287
00288
00289 MMS3DPM_ITEM *item = &this->pm_items[this->pm_items_cnt];
00290 this->pm_items_cnt++;
00291 item->type = type;
00292 memcpy(item->identifier, identifier, sizeof(identifier));
00293
00294
00295 if (vertices) {
00296 item->vertices = *vertices = this->varrays_cnt;
00297 this->varrays[item->vertices] = &this->vabuf[this->varrays_cnt];
00298 this->varrays_cnt++;
00299 this->varrays[this->varrays_cnt] = NULL;
00300 }
00301 else {
00302 item->vertices = -1;
00303 }
00304 if (normals) {
00305 item->normals = *normals = this->varrays_cnt;
00306 this->varrays[item->normals] = &this->vabuf[this->varrays_cnt];
00307 this->varrays_cnt++;
00308 this->varrays[this->varrays_cnt] = NULL;
00309 }
00310 else {
00311 item->normals = -1;
00312 }
00313 if (texcoords) {
00314 item->texcoords = *texcoords = varrays_cnt;
00315 varrays[item->texcoords] = &this->vabuf[this->varrays_cnt];
00316 varrays_cnt++;
00317 varrays[varrays_cnt] = NULL;
00318 }
00319 else {
00320 item->texcoords = -1;
00321 }
00322 if (indices) {
00323 item->indices = *indices = this->iarrays_cnt;
00324 this->iarrays[item->indices] = &this->iabuf[this->iarrays_cnt];
00325 this->iarrays_cnt++;
00326 this->iarrays[this->iarrays_cnt] = NULL;
00327 }
00328 else {
00329 item->indices = -1;
00330 }
00331
00332 switch (type) {
00333 case MMS3DPM_TYPE_RECTANGLE:
00334 genRectangle(identifier[0], identifier[1],
00335 (vertices) ? this->varrays[*vertices] : NULL,
00336 (normals) ? this->varrays[*normals] : NULL,
00337 (texcoords)? this->varrays[*texcoords]: NULL,
00338 (indices) ? this->iarrays[*indices] : NULL);
00339 break;
00340 case MMS3DPM_TYPE_SPHERE:
00341 genSphere(identifier[0], identifier[1],
00342 (vertices) ? this->varrays[*vertices] : NULL,
00343 (normals) ? this->varrays[*normals] : NULL,
00344 (texcoords)? this->varrays[*texcoords]: NULL,
00345 (indices) ? this->iarrays[*indices] : NULL);
00346 break;
00347 case MMS3DPM_TYPE_TORUS:
00348 genTorus(identifier[0], identifier[1], identifier[2], identifier[3],
00349 (vertices) ? this->varrays[*vertices] : NULL,
00350 (normals) ? this->varrays[*normals] : NULL,
00351 (texcoords)? this->varrays[*texcoords]: NULL,
00352 (indices) ? this->iarrays[*indices] : NULL);
00353 break;
00354 case MMS3DPM_TYPE_CYLINDER:
00355 genCylinder(identifier[0], identifier[1], identifier[2],
00356 (vertices) ? this->varrays[*vertices] : NULL,
00357 (normals) ? this->varrays[*normals] : NULL,
00358 (texcoords)? this->varrays[*texcoords]: NULL,
00359 (indices) ? this->iarrays[*indices] : NULL);
00360 break;
00361 }
00362
00363 return this->pm_items_cnt - 1;
00364 }
00365
00366 int MMS3DPolygonMesh::newPMItem(MMS3DPM_TYPE type, MMS3DPM_MESHID identifier,
00367 MMS_VERTEX_ARRAY *vertices, MMS_VERTEX_ARRAY *normals,
00368 MMS_VERTEX_ARRAY *texcoords, MMS_INDEX_ARRAY *indices) {
00369 if (this->pm_items_cnt >= MMS3DPM_ITEM_MAX) {
00370
00371 return -1;
00372 }
00373
00374
00375 MMS3DPM_ITEM *item = &this->pm_items[this->pm_items_cnt];
00376 this->pm_items_cnt++;
00377 item->type = type;
00378 memcpy(item->identifier, identifier, sizeof(identifier));
00379
00380
00381 if (vertices) {
00382 item->vertices = this->varrays_cnt;
00383 this->varrays[item->vertices] = &this->vabuf[this->varrays_cnt];
00384 this->varrays_cnt++;
00385 this->varrays[this->varrays_cnt] = NULL;
00386 }
00387 else {
00388 item->vertices = -1;
00389 }
00390 if (normals) {
00391 item->normals = this->varrays_cnt;
00392 this->varrays[item->normals] = &this->vabuf[this->varrays_cnt];
00393 this->varrays_cnt++;
00394 this->varrays[this->varrays_cnt] = NULL;
00395 }
00396 else {
00397 item->normals = -1;
00398 }
00399 if (texcoords) {
00400 item->texcoords = varrays_cnt;
00401 varrays[item->texcoords] = &this->vabuf[this->varrays_cnt];
00402 varrays_cnt++;
00403 varrays[varrays_cnt] = NULL;
00404 }
00405 else {
00406 item->texcoords = -1;
00407 }
00408 if (indices) {
00409 item->indices = this->iarrays_cnt;
00410 this->iarrays[item->indices] = &this->iabuf[this->iarrays_cnt];
00411 this->iarrays_cnt++;
00412 this->iarrays[this->iarrays_cnt] = NULL;
00413 }
00414 else {
00415 item->indices = -1;
00416 }
00417
00418
00419 if (item->vertices >= 0) {
00420 if (initVertexArray(this->varrays[item->vertices], vertices->eSize, vertices->eNum, vertices->dtype))
00421 memcpy(this->varrays[item->vertices]->data, vertices->data, getVertexArraySize(vertices));
00422 }
00423 if (item->normals >= 0) {
00424 if (initVertexArray(this->varrays[item->normals], normals->eSize, normals->eNum, normals->dtype))
00425 memcpy(this->varrays[item->normals]->data, normals->data, getVertexArraySize(normals));
00426 }
00427 if (item->texcoords >= 0) {
00428 if (initVertexArray(this->varrays[item->texcoords], texcoords->eSize, texcoords->eNum, texcoords->dtype))
00429 memcpy(this->varrays[item->texcoords]->data, texcoords->data, getVertexArraySize(texcoords));
00430 }
00431 if (item->indices >= 0) {
00432 if (initIndexArray(this->iarrays[item->indices], indices->type, indices->eNum))
00433 memcpy(this->iarrays[item->indices]->data, indices->data, getIndexArraySize(indices));
00434 }
00435
00436 return this->pm_items_cnt - 1;
00437 }
00438
00439 void MMS3DPolygonMesh::getArrays(MMS_VERTEX_ARRAY ***varrays, MMS_INDEX_ARRAY ***iarrays) {
00440 *varrays = this->varrays;
00441 *iarrays = this->iarrays;
00442 }
00443
00444 bool MMS3DPolygonMesh::setPrimitives(string id, MMS_VERTEX_ARRAY *vertices, MMS_VERTEX_ARRAY *normals,
00445 MMS_VERTEX_ARRAY *texcoords, MMS_INDEX_ARRAY *indices) {
00446 MMS3DPM_MESHID identifier;
00447 memset(&identifier[0], 0, sizeof(identifier));
00448 int len = id.size();
00449 if (len >= sizeof(identifier))
00450 len = sizeof(identifier) - 1;
00451 memcpy(&identifier[0], id.c_str(), len);
00452
00453 if (findPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, NULL, NULL, NULL, NULL) < 0) {
00454
00455 return (newPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, vertices, normals, texcoords, indices) >= 0);
00456 }
00457
00458
00459 return false;
00460 }
00461
00462 bool MMS3DPolygonMesh::getPrimitives(string id, int *vertices, int *normals, int *texcoords, int *indices) {
00463 MMS3DPM_MESHID identifier;
00464 memset(&identifier[0], 0, sizeof(identifier));
00465 int len = id.size();
00466 if (len >= sizeof(identifier))
00467 len = sizeof(identifier) - 1;
00468 memcpy(&identifier[0], id.c_str(), len);
00469
00470 return (findPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, vertices, normals, texcoords, indices) >= 0);
00471 }
00472
00473 bool MMS3DPolygonMesh::genRectangle(float width, float height, int *vertices, int *normals, int *texcoords, int *indices) {
00474 MMS3DPM_MESHID identifier = {width, height, 0, 0, 0, 0, 0, 0};
00475 if (findPMItem(MMS3DPM_TYPE_RECTANGLE, identifier, vertices, normals, texcoords, indices) < 0) {
00476
00477 return (newPMItem(MMS3DPM_TYPE_RECTANGLE, identifier, vertices, normals, texcoords, indices) >= 0);
00478 }
00479 return true;
00480 }
00481
00482 bool MMS3DPolygonMesh::genSphere(int numSlices, float radius, int *vertices, int *normals, int *texcoords, int *indices) {
00483 MMS3DPM_MESHID identifier = {numSlices, radius, 0, 0, 0, 0, 0, 0};
00484 if (findPMItem(MMS3DPM_TYPE_SPHERE, identifier, vertices, normals, texcoords, indices) < 0) {
00485
00486 return (newPMItem(MMS3DPM_TYPE_SPHERE, identifier, vertices, normals, texcoords, indices) >= 0);
00487 }
00488 return true;
00489 }
00490
00491 bool MMS3DPolygonMesh::genTorus(int numwraps, int numperwrap, float majorradius, float minorradius,
00492 int *vertices, int *normals, int *texcoords, int *indices) {
00493 MMS3DPM_MESHID identifier = {numwraps, numperwrap, majorradius, minorradius, 0, 0, 0, 0};
00494 if (findPMItem(MMS3DPM_TYPE_TORUS, identifier, vertices, normals, texcoords, indices) < 0) {
00495
00496 return (newPMItem(MMS3DPM_TYPE_TORUS, identifier, vertices, normals, texcoords, indices) >= 0);
00497 }
00498 return true;
00499 }
00500
00501 bool MMS3DPolygonMesh::genCylinder(int numSlices, float height, float radius,
00502 int *vertices, int *normals, int *texcoords, int *indices) {
00503 MMS3DPM_MESHID identifier = {numSlices, height, radius, 0, 0, 0, 0, 0};
00504 if (findPMItem(MMS3DPM_TYPE_CYLINDER, identifier, vertices, normals, texcoords, indices) < 0) {
00505
00506 return (newPMItem(MMS3DPM_TYPE_CYLINDER, identifier, vertices, normals, texcoords, indices) >= 0);
00507 }
00508 return true;
00509 }
00510
00511
00512