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, 8 * sizeof(float)))
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, 8 * sizeof(float));
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 case MMS3DPM_TYPE_PRIMITIVES:
00362 break;
00363 }
00364
00365 return this->pm_items_cnt - 1;
00366 }
00367
00368 int MMS3DPolygonMesh::newPMItem(MMS3DPM_TYPE type, MMS3DPM_MESHID identifier,
00369 MMS_VERTEX_ARRAY *vertices, MMS_VERTEX_ARRAY *normals,
00370 MMS_VERTEX_ARRAY *texcoords, MMS_INDEX_ARRAY *indices) {
00371 if (this->pm_items_cnt >= MMS3DPM_ITEM_MAX) {
00372
00373 return -1;
00374 }
00375
00376
00377 MMS3DPM_ITEM *item = &this->pm_items[this->pm_items_cnt];
00378 this->pm_items_cnt++;
00379 item->type = type;
00380 memcpy(item->identifier, identifier, 8 * sizeof(float));
00381
00382
00383 if (vertices) {
00384 item->vertices = this->varrays_cnt;
00385 this->varrays[item->vertices] = &this->vabuf[this->varrays_cnt];
00386 this->varrays_cnt++;
00387 this->varrays[this->varrays_cnt] = NULL;
00388 }
00389 else {
00390 item->vertices = -1;
00391 }
00392 if (normals) {
00393 item->normals = this->varrays_cnt;
00394 this->varrays[item->normals] = &this->vabuf[this->varrays_cnt];
00395 this->varrays_cnt++;
00396 this->varrays[this->varrays_cnt] = NULL;
00397 }
00398 else {
00399 item->normals = -1;
00400 }
00401 if (texcoords) {
00402 item->texcoords = varrays_cnt;
00403 varrays[item->texcoords] = &this->vabuf[this->varrays_cnt];
00404 varrays_cnt++;
00405 varrays[varrays_cnt] = NULL;
00406 }
00407 else {
00408 item->texcoords = -1;
00409 }
00410 if (indices) {
00411 item->indices = this->iarrays_cnt;
00412 this->iarrays[item->indices] = &this->iabuf[this->iarrays_cnt];
00413 this->iarrays_cnt++;
00414 this->iarrays[this->iarrays_cnt] = NULL;
00415 }
00416 else {
00417 item->indices = -1;
00418 }
00419
00420
00421 if (item->vertices >= 0) {
00422 if (initVertexArray(this->varrays[item->vertices], vertices->eSize, vertices->eNum, vertices->dtype))
00423 memcpy(this->varrays[item->vertices]->data, vertices->data, getVertexArraySize(vertices));
00424 }
00425 if (item->normals >= 0) {
00426 if (initVertexArray(this->varrays[item->normals], normals->eSize, normals->eNum, normals->dtype))
00427 memcpy(this->varrays[item->normals]->data, normals->data, getVertexArraySize(normals));
00428 }
00429 if (item->texcoords >= 0) {
00430 if (initVertexArray(this->varrays[item->texcoords], texcoords->eSize, texcoords->eNum, texcoords->dtype))
00431 memcpy(this->varrays[item->texcoords]->data, texcoords->data, getVertexArraySize(texcoords));
00432 }
00433 if (item->indices >= 0) {
00434 if (initIndexArray(this->iarrays[item->indices], indices->type, indices->eNum))
00435 memcpy(this->iarrays[item->indices]->data, indices->data, getIndexArraySize(indices));
00436 }
00437
00438 return this->pm_items_cnt - 1;
00439 }
00440
00441 void MMS3DPolygonMesh::getArrays(MMS_VERTEX_ARRAY ***varrays, MMS_INDEX_ARRAY ***iarrays) {
00442 *varrays = this->varrays;
00443 *iarrays = this->iarrays;
00444 }
00445
00446 bool MMS3DPolygonMesh::setPrimitives(string id, MMS_VERTEX_ARRAY *vertices, MMS_VERTEX_ARRAY *normals,
00447 MMS_VERTEX_ARRAY *texcoords, MMS_INDEX_ARRAY *indices) {
00448 MMS3DPM_MESHID identifier;
00449 memset(&identifier[0], 0, sizeof(identifier));
00450 int len = id.size();
00451 if (len >= sizeof(identifier))
00452 len = sizeof(identifier) - 1;
00453 memcpy(&identifier[0], id.c_str(), len);
00454
00455 if (findPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, NULL, NULL, NULL, NULL) < 0) {
00456
00457 return (newPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, vertices, normals, texcoords, indices) >= 0);
00458 }
00459
00460
00461 return false;
00462 }
00463
00464 bool MMS3DPolygonMesh::getPrimitives(string id, int *vertices, int *normals, int *texcoords, int *indices) {
00465 MMS3DPM_MESHID identifier;
00466 memset(&identifier[0], 0, sizeof(identifier));
00467 int len = id.size();
00468 if (len >= sizeof(identifier))
00469 len = sizeof(identifier) - 1;
00470 memcpy(&identifier[0], id.c_str(), len);
00471
00472 return (findPMItem(MMS3DPM_TYPE_PRIMITIVES, identifier, vertices, normals, texcoords, indices) >= 0);
00473 }
00474
00475 bool MMS3DPolygonMesh::genRectangle(float width, float height, int *vertices, int *normals, int *texcoords, int *indices) {
00476 MMS3DPM_MESHID identifier = {width, height, 0, 0, 0, 0, 0, 0};
00477 if (findPMItem(MMS3DPM_TYPE_RECTANGLE, identifier, vertices, normals, texcoords, indices) < 0) {
00478
00479 return (newPMItem(MMS3DPM_TYPE_RECTANGLE, identifier, vertices, normals, texcoords, indices) >= 0);
00480 }
00481 return true;
00482 }
00483
00484 bool MMS3DPolygonMesh::genSphere(int numSlices, float radius, int *vertices, int *normals, int *texcoords, int *indices) {
00485 MMS3DPM_MESHID identifier = {numSlices, radius, 0, 0, 0, 0, 0, 0};
00486 if (findPMItem(MMS3DPM_TYPE_SPHERE, identifier, vertices, normals, texcoords, indices) < 0) {
00487
00488 return (newPMItem(MMS3DPM_TYPE_SPHERE, identifier, vertices, normals, texcoords, indices) >= 0);
00489 }
00490 return true;
00491 }
00492
00493 bool MMS3DPolygonMesh::genTorus(int numwraps, int numperwrap, float majorradius, float minorradius,
00494 int *vertices, int *normals, int *texcoords, int *indices) {
00495 MMS3DPM_MESHID identifier = {numwraps, numperwrap, majorradius, minorradius, 0, 0, 0, 0};
00496 if (findPMItem(MMS3DPM_TYPE_TORUS, identifier, vertices, normals, texcoords, indices) < 0) {
00497
00498 return (newPMItem(MMS3DPM_TYPE_TORUS, identifier, vertices, normals, texcoords, indices) >= 0);
00499 }
00500 return true;
00501 }
00502
00503 bool MMS3DPolygonMesh::genCylinder(int numSlices, float height, float radius,
00504 int *vertices, int *normals, int *texcoords, int *indices) {
00505 MMS3DPM_MESHID identifier = {numSlices, height, radius, 0, 0, 0, 0, 0};
00506 if (findPMItem(MMS3DPM_TYPE_CYLINDER, identifier, vertices, normals, texcoords, indices) < 0) {
00507
00508 return (newPMItem(MMS3DPM_TYPE_CYLINDER, identifier, vertices, normals, texcoords, indices) >= 0);
00509 }
00510 return true;
00511 }
00512
00513
00514