00001
00002
00003
00004
00005 #if defined(_WIN32) // SYK 5/09/06 for VC++ 2005
00006 #pragma warning (disable:4355)
00007 #endif // _WIN32
00008
00009 #include "object.h"
00010
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <assert.h>
00014 #include <time.h>
00015 #include <sys/timeb.h>
00016
00017 #ifdef _WIN32
00018 #else
00019 #include <strings.h>
00020 #endif
00021
00022 #include "springCore.h"
00023 #include "objectarray.h"
00024 #include "tetraarray.h"
00025 #include "facearray.h"
00026 #include "edgearray.h"
00027 #include "nodearray.h"
00028
00029 #include "node.h"
00030 #include "edge.h"
00031 #include "face.h"
00032 #include "tetra.h"
00033
00034 #include "point3d.h"
00035 #include "cyberware.h"
00036 #include "rasterfont.h"
00037 #include "geometryreplicator.h"
00038 #include "perlinnoise.h"
00039
00040 #include "space.h"
00041 #include "triangles.h"
00042 #include "void.h"
00043
00044 #include "haptic_v1.h"
00045 #include "haptic_v2.h"
00046
00047 #ifndef _WIN32
00048
00049 #define _fileno fileno
00050 #endif // _WIN32
00051
00052 #include "glui.h"
00053
00054
00055 #ifdef __APPLE__
00056 #include <OpenGL/gl.h>
00057 #else
00058 #include <GL/gl.h>
00059 #endif // __APPLE__
00060
00061
00062
00063 const char* Object::rcsid = "@(#) $Id: object.cpp,v 1.249 2006/05/30 20:25:19 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00064 int Object::debug = 0;
00065
00066
00067 static GLfloat default_deformable_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
00068 static GLfloat default_deformable_mat_diffuse[] = { 0.9f, 0.35f, 0.2f, 1.0f };
00069 static GLfloat default_deformable_mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00070 static GLfloat default_deformable_mat_shininess[] = { 128.0f };
00071
00072
00073 static GLfloat default_articulate_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
00074 static GLfloat default_articulate_mat_diffuse[] = { 0.9f, 0.35f, 0.2f, 1.0f };
00075 static GLfloat default_articulate_mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00076 static GLfloat default_articulate_mat_shininess[] = { 128.0f };
00077
00078
00079 static GLfloat default_rigid_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
00080 static GLfloat default_rigid_mat_diffuse[] = { 0.8f, 0.65f, 0.5f, 1.0f };
00081 static GLfloat default_rigid_mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00082 static GLfloat default_rigid_mat_shininess[] = { 128.0f };
00083
00084
00085 static GLfloat default_rest_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
00086 static GLfloat default_rest_mat_diffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f };
00087 static GLfloat default_rest_mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00088 static GLfloat default_rest_mat_shininess[] = { 100.0 };
00089
00090
00091 static GLfloat default_button_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
00092 static GLfloat default_button_mat_diffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f };
00093 static GLfloat default_button_mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
00094 static GLfloat default_button_mat_shininess[] = { 100.0 };
00095
00096 Object::Object()
00097 : nodearray(this),
00098 edgearray(&nodearray),
00099 facearray(&nodearray,&edgearray),
00100 tetraarray(&nodearray,&edgearray,&facearray)
00101 {
00102 if (debug) cerr << "Object::constructor()\n";
00103 objectarray_p = NULL;
00104 type = nodes_only;
00105 dynamics = deformable;
00106 behavior = none;
00107 nummethod = quasi_ordered;
00108 visible = 1;
00109 selected = 0;
00110 texture = NULL;
00111 nodearray.Init(&edgearray);
00112 strncpy(name, "UNINITIALIZED", NAME_LENGTH);
00113 sensor_p = NULL;
00114 linked_part = 0;
00115 tip_node = 0;
00116 drawover_amount = 0.0;
00117 being_modified = 0;
00118
00119 IsAScreen = 0;
00120 group_number = 0;
00121
00122 closest_node = NULL;
00123 being_grabbed = 0;
00124 do_deform_only_on_grab = 0;
00125 do_preserve_volume = 0;
00126 sensor_offset = Point3D(0,0,0);
00127 uses_viagra = 0;
00128
00129
00130
00131
00132 collision_extent = no_collisions;
00133
00134 collision_force = penetration_depth_force;
00135
00136 boundingBoxRoot = NULL;
00137
00138 boundingSphereRoot = NULL;
00139
00140 maxLevelCollisionCheck = (int)1e6;
00141
00142 ConstructCollisions();
00143
00144
00145
00146 label_offset = 0.0;
00147
00148
00149 dl_needs_refresh = 1;
00150 dl_id = -1;
00151
00152
00153 display_mode.mode = DisplayMode::smooth;
00154 display_mode.draw_subobjcolormode = 0;
00155 last_display_mode = display_mode;
00156
00157
00158 height = 0;
00159
00160
00161 hinges.Init();
00162
00163
00164 rigidHinge = NULL;
00165
00166
00167 set_default_material_properties();
00168 timer.Reset();
00169
00170
00171 current_attribute_menu = NULL;
00172 }
00173
00174 Object::~Object()
00175 {
00176 if (debug) cerr << "Object[" << name << "]::destructor()\n";
00177 strncpy(name, "DESTROYED", NAME_LENGTH);
00178
00179
00180
00181 DestructCollisions();
00182
00183
00184
00185
00186
00187
00188
00189 if (sensor_p) sensor_p->LinkToObject(NULL);
00190 }
00191
00192 void Object::Init(ObjectArray* objectarray_in, char* name_in)
00193 {
00194 objectarray_p = objectarray_in;
00195 if (!name_in) name_in = "UNNAMED";
00196 strncpy(name, name_in, NAME_LENGTH);
00197 strncpy(path, "", PATH_LENGTH);
00198 objextrusions = 0;
00199 }
00200
00201 void Object::set_default_material_properties()
00202
00203 {
00204 if (debug)
00205 cerr << "Object[" << getName() << "]:set_default_material_properties()\n";
00206
00207 switch (dynamics) {
00208 case rest:
00209 memcpy(mat_ambient, default_rest_mat_ambient, 4*sizeof(float));
00210 memcpy(mat_diffuse, default_rest_mat_diffuse, 4*sizeof(float));
00211 memcpy(mat_specular, default_rest_mat_specular, 4*sizeof(float));
00212 memcpy(mat_shininess, default_rest_mat_shininess, 1*sizeof(float));
00213 break;
00214 case rigid:
00215 memcpy(mat_ambient, default_rigid_mat_ambient, 4*sizeof(float));
00216 memcpy(mat_diffuse, default_rigid_mat_diffuse, 4*sizeof(float));
00217 memcpy(mat_specular, default_rigid_mat_specular, 4*sizeof(float));
00218 memcpy(mat_shininess, default_rigid_mat_shininess, 1*sizeof(float));
00219 break;
00220 case deformable:
00221 memcpy(mat_ambient, default_deformable_mat_ambient, 4*sizeof(float));
00222 memcpy(mat_diffuse, default_deformable_mat_diffuse, 4*sizeof(float));
00223 memcpy(mat_specular, default_deformable_mat_specular, 4*sizeof(float));
00224 memcpy(mat_shininess, default_deformable_mat_shininess, 1*sizeof(float));
00225 break;
00226 case articulate:
00227 memcpy(mat_ambient, default_articulate_mat_ambient, 4*sizeof(float));
00228 memcpy(mat_diffuse, default_articulate_mat_diffuse, 4*sizeof(float));
00229 memcpy(mat_specular, default_articulate_mat_specular, 4*sizeof(float));
00230 memcpy(mat_shininess, default_articulate_mat_shininess, 1*sizeof(float));
00231 break;
00232 case button:
00233 memcpy(mat_ambient, default_button_mat_ambient, 4*sizeof(float));
00234 memcpy(mat_diffuse, default_button_mat_diffuse, 4*sizeof(float));
00235 memcpy(mat_specular, default_button_mat_specular, 4*sizeof(float));
00236 memcpy(mat_shininess, default_button_mat_shininess, 1*sizeof(float));
00237 break;
00238 }
00239
00240
00241 memcpy(back_mat_ambient, mat_ambient, 4*sizeof(float));
00242 memcpy(back_mat_diffuse, mat_diffuse, 4*sizeof(float));
00243 memcpy(back_mat_specular, mat_specular, 4*sizeof(float));
00244 memcpy(back_mat_shininess, mat_shininess, 1*sizeof(float));
00245 }
00246
00247
00248 int Object::ReadAmira(FILE* fp)
00249 {
00250 if (debug) cerr << "Object[" << name << "]::ReadAmira("
00251 << int(fp) << ")\n";
00252
00253 dynamics = rigid;
00254 set_default_material_properties();
00255 type = tetras_only;
00256
00257 int num_nodes = 0;
00258 int num_tetra = 0;
00259
00260 char s[MAXLINE];
00261 myfgets(s, MAXLINE, fp);
00262 int num_args = sscanf(s, "%d %d", &num_nodes, &num_tetra);
00263
00264 if (num_args < 2) {
00265 cerr << "bad file" << endl;
00266 return 0;
00267 }
00268
00269 int status;
00270 if ((status = nodearray.getAmiraNodeData(fp,num_nodes)) == 0)
00271 return(status);
00272
00273
00274 status = tetraarray.getAmiraTetraData(fp,num_tetra);
00275
00276
00277
00278
00279
00280
00281 setTexture(NULL);
00282
00283
00284 return(status);
00285 }
00286
00287 int Object::ReadMesh(FILE* fp)
00288 {
00289 if (debug) cerr << "Object[" << name << "]::ReadMesh(" << int(fp) << ")\n";
00290
00291 {
00292 char s[MAXLINE];
00293 myfgets(s, MAXLINE, fp);
00294 int obj_num, group_num, dummy;
00295 int num_args = sscanf(s, "%d %d %d", &obj_num, &group_num, &dummy);
00296 if (num_args == 2) {
00297 if (debug) cerr << "newer style mesh file\n";
00298 if (group_num == 3) dynamics = rest;
00299 else dynamics = deformable;
00300
00301 myfgets(s, MAXLINE, fp);
00302 myfgets(s, MAXLINE, fp);
00303 } else {
00304 if (debug) cerr << "older style mesh file\n";
00305 dynamics = deformable;
00306 }
00307
00308
00309 set_default_material_properties();
00310 }
00311
00312
00313 type = nodes_only;
00314
00315
00316 int status;
00317 if ((status = nodearray.getMeshNodeData(fp)) == 0)
00318 return(status);
00319
00320
00321 status = facearray.getMeshFaceData(fp);
00322
00323
00324 type = faces_only;
00325
00326 #define RECALC_NORMALS_ON_READ
00327 #ifdef RECALC_NORMALS_ON_READ
00328
00329 facearray.computeNormals();
00330
00331
00332 nodearray.interpolateNormals();
00333 #endif
00334
00335
00336 setTexture(NULL);
00337
00338
00339 if (dynamics == deformable) {
00340 setNumMethod(Object::numerical_method(5));
00341 getEdgeArray()->setSpringConstants(100.0);
00342 getNodeArray()->setVelocityDampConstants(100.0);
00343 }
00344
00345
00346 return(status);
00347 }
00348
00349 int Object::ReadSMF(FILE* fp)
00350 {
00351 if (debug) cerr << "Object[" << name << "]::ReadSMF(" << int(fp) << ")\n";
00352
00353
00354 dynamics = rigid;
00355
00356
00357 set_default_material_properties();
00358
00359
00360 type = faces_only;
00361
00362
00363 int status;
00364 if ((status = nodearray.getSMFNodeData(fp)) == 0)
00365 return(status);
00366
00367
00368 status = facearray.getSMFFaceData(fp);
00369
00370
00371 facearray.computeNormals();
00372
00373
00374 nodearray.interpolateNormals();
00375
00376
00377 nodearray.computeTextureCoords(Node::cylindrical);
00378
00379
00380 setTexture(NULL);
00381
00382
00383 return(status);
00384 }
00385
00386
00387 int Object::ReadOBJ(FILE* fp)
00388 {
00389 if (debug) cerr << "Object[" << name << "]::ReadOBJ(" << int(fp) << ")\n";
00390
00391
00392 dynamics = rest;
00393
00394
00395 set_default_material_properties();
00396
00397
00398 type = faces_only;
00399
00400
00401 int status = nodearray.getOBJNodeData(fp);
00402 if (status == 0) {
00403
00404
00405 return(status);
00406
00407 }
00408
00409 else if (status == 1) {
00410
00411
00412
00413 nodearray.computeTextureCoords(Node::cylindrical);
00414
00415 }
00416
00417
00418 status = facearray.getOBJFaceData(fp);
00419
00420
00421 facearray.computeNormals();
00422
00423
00424 nodearray.interpolateNormals();
00425
00426
00427 setTexture(NULL);
00428
00429
00430 return(status);
00431 }
00432
00433
00434
00435
00436 int Object::ReadSOBJ(FILE* fp)
00437 {
00438
00439 int status = 0;
00440
00441
00442 char buffer[256];
00443 char object_name[80];
00444
00445
00446 fgets(buffer, 256, fp);
00447 sscanf(buffer, "%s", object_name);
00448
00449
00450 if (!strcmp(object_name, "sphere")) {
00451
00452 float layers, radius, inner;
00453 sscanf(buffer, "%*s %f %f %f", &layers, &radius, &inner);
00454
00455
00456 status = CreateSphere((int)layers, radius, inner);
00457 }
00458 else if (!strcmp(object_name, "plane")) {
00459
00460 float x_length, y_length;
00461 int x_steps, y_steps;
00462 float x_offset, y_offset, z_offset;
00463 char orientation;
00464 sscanf(buffer, "%*s %f %f %d %d %f %f %f %c", &x_length, &y_length, &x_steps, &y_steps,
00465 &x_offset, &y_offset, &z_offset, &orientation);
00466
00467 CreatePlane(x_length, y_length, x_steps, y_steps,
00468 Point3D(x_offset, y_offset, z_offset), orientation);
00469 }
00470
00471
00472 return(status);
00473 }
00474
00475 int Object::ReadFRD(FILE* fp)
00476 {
00477 if (debug) cerr << "Object[" << name << "]::ReadFRD(" << int(fp) << ")\n";
00478
00479 char s[MAXLINE];
00480 int dyn;
00481 float Rred, Ggreen, Bblue, Aalpha;
00482
00483
00484 set_default_material_properties();
00485
00486
00487 type = faces_only;
00488
00489
00490 int status;
00491 if ((status = nodearray.getSMFNodeData(fp)) == 0)
00492 return(status);
00493
00494
00495 status = edgearray.getFRDEdgeData(fp);
00496
00497
00498 status = facearray.getSMFFaceData(fp);
00499
00500
00501 myfgets(s, MAXLINE, fp);
00502 if (s[0] == 'o')
00503 sscanf(s, "%*c %d", &objextrusions);
00504 else {
00505 printf("Bad read on objextrusions. objextrusions will be set to 0\n");
00506 objextrusions = 0;;
00507 }
00508
00509 myfgets(s, MAXLINE, fp);
00510 if (s[0] == 'd'){
00511 sscanf(s, "%*c %d", &dyn);
00512 setDynamics(dynamics_type(dyn));
00513 }
00514 else {
00515 printf("Bad read on dynamics. Dynamics will be set to rest\n");
00516 dynamics = rest;
00517 }
00518
00519 myfgets(s, MAXLINE, fp);
00520 if (s[0] == 'r')
00521 sscanf(s, "%*c %e", &Rred);
00522 else {
00523 printf("Bad read on red color. Red color will be set to 0.5\n");
00524 Rred = 0.5;
00525 }
00526 myfgets(s, MAXLINE, fp);
00527 if (s[0] == 'g')
00528 sscanf(s, "%*c %e", &Ggreen);
00529 else {
00530 printf("Bad read on green color. Green color will be set to 0.5\n");
00531 Ggreen = 0.5;
00532 }
00533 myfgets(s, MAXLINE, fp);
00534 if (s[0] == 'b')
00535 sscanf(s, "%*c %e", &Bblue);
00536 else {
00537 printf("Bad read on blue color. Blue color will be set to 0.5\n");
00538 Bblue = 0.5;
00539 }
00540 myfgets(s, MAXLINE, fp);
00541 if (s[0] == 'a')
00542 sscanf(s, "%*c %e", &Aalpha);
00543 else {
00544 printf("Bad read on alpha. Alpha will be set to 0.5\n");
00545 Aalpha = 0.5;
00546 }
00547
00548 setDiffuseColor(Rred, Ggreen, Bblue, Aalpha);
00549
00550 myfgets(s, MAXLINE, fp);
00551 if (s[0] == 'n')
00552 sscanf(s, "%*c %d", &Nb_face_surf);
00553 else {
00554 printf("Bad read on the # of faces on the original mesh.\nIt will be set to the actual # of faces of this object\n");
00555 Nb_face_surf = facearray.getNumFaces();;
00556 }
00557
00558 double tempmass, tempspring, tempdamp;
00559 myfgets(s, MAXLINE, fp);
00560 if (s[0] == 'm')
00561 sscanf(s, "%*c %lf", &tempmass);
00562 else {
00563 printf("Bad read on the mass constant on the original mesh.\nIt will be set to 1\n");
00564 nodearray.setMasses(1.0);
00565 }
00566 nodearray.setMasses(tempmass);
00567
00568 myfgets(s, MAXLINE, fp);
00569 if (s[0] == 's')
00570 sscanf(s, "%*c %lf", &tempspring);
00571 else {
00572 printf("Bad read on the spring constant on the original mesh.\nIt will be set to 1\n");
00573 edgearray.setSpringConstants(1.0);
00574 }
00575 edgearray.setSpringConstants(tempspring);
00576
00577 myfgets(s, MAXLINE, fp);
00578 if (s[0] == 'p')
00579 sscanf(s, "%*c %lf", &tempdamp);
00580 else {
00581 printf("Bad read on the damp constant on the original mesh.\nIt will be set to 1\n");
00582 nodearray.setVelocityDampConstants(1.0);
00583 }
00584 nodearray.setVelocityDampConstants(tempdamp);
00585
00586
00587
00588 facearray.computeNormals();
00589
00590
00591 nodearray.interpolateNormals();
00592
00593
00594 nodearray.computeTextureCoords(Node::cylindrical);
00595
00596
00597 setTexture(NULL);
00598
00599
00600 return(status);
00601 }
00602
00603 char* get_next_token(char* buffer, int bufsize, FILE* fp)
00604 {
00605 char* delimiters = " \t\n\r,";
00606 char* ptr = strtok(NULL, delimiters);
00607
00608 while (!ptr && !feof(fp)) {
00609 char* b = myfgets(buffer, bufsize, fp);
00610 ptr = strtok(b, delimiters);
00611 }
00612 return(ptr);
00613 }
00614
00615
00616
00617
00618
00619
00620 int Object::ReadVRML(FILE* fp, int create_subobjects)
00621 {
00622 if (debug) cerr << "Object[" << name << "]::ReadVRML(" << int(fp) << ")\n";
00623
00624
00625 const int bufsize = 256;
00626 static char buffer[bufsize];
00627 strtok(buffer, "\0");
00628
00629
00630 fgets(buffer, bufsize, fp);
00631 strtok(buffer, "\n");
00632 int is_vrml2 = 0;
00633 if (strstr(buffer, "2.")) is_vrml2 = 1;
00634 if (debug) {
00635 cerr << "file type buffer is [" << buffer << "]\n";
00636 cerr << "File format is : ";
00637 if (is_vrml2) cerr << "VRML2.0\n";
00638 else cerr << "VRML1.0\n";
00639 }
00640
00641
00642 Matrix initial_xform;
00643
00644
00645 int status = ReadVRMLObject(fp, initial_xform, create_subobjects, is_vrml2);
00646
00647
00648 return(status);
00649 }
00650
00651
00652 int Object::ReadVRMLObject(FILE* fp, Matrix original_xform, int create_subobjects, int is_vrml2)
00653 {
00654 if (debug) cerr << "Object[" << name << "]::ReadVRMLObject(" << int(fp) << ", xform, " << create_subobjects << ", " << is_vrml2 << ")\n";
00655
00656 int status = 1;
00657
00658
00659 dynamics = rest;
00660
00661
00662 set_default_material_properties();
00663
00664
00665 type = faces_only;
00666
00667
00668
00669
00670
00671 const int bufsize = 256;
00672 static char buffer[bufsize];
00673 strtok(buffer, "\0");
00674
00675
00676 int nesting = 1;
00677 int last_block_of_coords_index = 0;
00678 int cur_part_id = -1;
00679 int num_defs = 0;
00680 ReallocableArray<float> texture_u, texture_v;
00681
00682
00683 Matrix local_xform;
00684 int local_trans_nest_level = 0, local_rot_nest_level = 0,
00685 local_scale_nest_level = 0;
00686
00687
00688 while (!feof(fp) && (nesting > 0)) {
00689
00690
00691 char* ptr = get_next_token(buffer, bufsize, fp);
00692 if (!ptr) break;
00693
00694 {
00695
00696
00697
00698
00699 if (strstr(ptr, "{") || strstr(ptr,"[")) nesting++;
00700 else if (strstr(ptr, "}") || strstr(ptr, "]")) nesting--;
00701 else if (!strcmp(ptr, "DEF")) {
00702 ptr = get_next_token(buffer, bufsize, fp);
00703 setName(ptr);
00704 num_defs++;
00705 cerr << num_defs << ": DEF of [" << ptr << "]\n";
00706 if (create_subobjects) {
00707
00708
00709 Matrix composite_xform;
00710 composite_xform.Multiply(original_xform);
00711 composite_xform.Multiply(local_xform);
00712
00713
00714
00715
00716
00717 Object* new_obj = objectarray_p->addObject(ptr);
00718 new_obj->ReadVRMLObject(fp, composite_xform, ++create_subobjects, is_vrml2);
00719 }
00720 }
00721 else if (!strcmp(ptr, "Coordinate3")) {
00722
00723
00724 cur_part_id++;
00725
00726
00727 last_block_of_coords_index = nodearray.getNumNodes();
00728 ReallocableArray<Point3D> local_pts;
00729 int subnesting = 0;
00730 do {
00731 ptr = get_next_token(buffer, bufsize, fp);
00732 if (!ptr) break;
00733
00734 if (strstr(ptr, "{") || strstr(ptr, "[")) subnesting++;
00735 else if (strstr(ptr, "}") || strstr(ptr, "]")) subnesting--;
00736 else if (!strcmp(ptr, "point")) continue;
00737 else {
00738 float x,y,z;
00739 x = atof(ptr);
00740 ptr = get_next_token(buffer, bufsize, fp);
00741 y = atof(ptr);
00742 ptr = get_next_token(buffer, bufsize, fp);
00743 z = atof(ptr);
00744 Point3D p(x,y,z);
00745
00746
00747 local_pts.Append(p);
00748
00749
00750 if (strstr(ptr, "}") || strstr(ptr, "]")) subnesting--;
00751 }
00752
00753
00754 } while (subnesting > 0);
00755
00756
00757 int num_read = local_pts.NumElements();
00758 cerr << "...read " << num_read << " nodes\n";
00759 nodearray.allocateNodes((int)(num_read * 1.10));
00760 edgearray.allocateEdges((int)(num_read * 2 * 1.10));
00761
00762
00763 Matrix composite_xform;
00764 composite_xform.Multiply(original_xform);
00765 composite_xform.Multiply(local_xform);
00766
00767
00768
00769
00770 for (int i=0; i<local_pts.NumElements(); i++) {
00771 Point3D p = local_pts[i];
00772 p.Xform(composite_xform.m);
00773
00774
00775 int index = nodearray.addNode(p);
00776 Node* node = nodearray.getNode(index);
00777 node->setPartId(cur_part_id);
00778 }
00779 }
00780 else if (!strcmp(ptr, "coordIndex")) {
00781 ReallocableArray<iPoint3D> local_faces;
00782 int subnesting = 0, num_read = 0;
00783 do {
00784 ptr = get_next_token(buffer, bufsize, fp);
00785
00786 if (strstr(ptr, "{") || strstr(ptr, "[")) { subnesting++; continue; }
00787 if (strstr(ptr, "}") || strstr(ptr, "]")) { subnesting--; continue; }
00788
00789 int i1, i2, i3;
00790 i1 = atoi(ptr);
00791 ptr = get_next_token(buffer, bufsize, fp);
00792 i2 = atoi(ptr);
00793 ptr = get_next_token(buffer, bufsize, fp);
00794 i3 = atoi(ptr);
00795
00796 if ((i1 < 0) || (i2 < 0)) {
00797 cerr << " face[ " << facearray.getNumFaces() << "] has indices " << i1 << ", " << i2 << endl;
00798 }
00799 else {
00800 int is_two_params = (i3 == -1);
00801
00802
00803 i1 += last_block_of_coords_index;
00804 i2 += last_block_of_coords_index;
00805 i3 += last_block_of_coords_index;
00806
00807 int nn = nodearray.getNumNodes();
00808 if ((i1 >= nn) || (i2 >= nn) || (i3 >= nn)) {
00809 cerr << " face[ " << facearray.getNumFaces() << "] has indices beyond bounds (" << nn << "): "
00810 << i1 << ", " << i2 << ", " << i3 << endl;
00811 }
00812 else if (!is_two_params) {
00813 ptr = get_next_token(buffer, bufsize, fp);
00814 iPoint3D temp(i1, i2, i3);
00815 local_faces.Append(temp);
00816 num_read++;
00817 }
00818 else {
00819 type = edges_only;
00820 display_mode.mode = DisplayMode::wireframe;
00821 edgearray.addEdge(i1,i2);
00822 cerr << "edge is " << i1 << " " << i2 << endl;
00823 num_read++;
00824 }
00825 }
00826
00827 } while (subnesting > 0);
00828 cerr << "...read " << num_read << " faces\n";
00829
00830
00831 facearray.allocateFaces((int)(num_read * 1.10));
00832
00833
00834 for (int i=0; i<local_faces.NumElements(); i++) {
00835 iPoint3D temp = local_faces[i];
00836 facearray.addFace(temp.x, temp.y, temp.z);
00837 }
00838 }
00839 else if (!strcmp(ptr, "TextureCoordinate2")) {
00840
00841
00842 int subnesting = 0;
00843 do {
00844 ptr = get_next_token(buffer, bufsize, fp);
00845 if (!ptr) break;
00846
00847 if (strstr(ptr, "{") || strstr(ptr, "[")) subnesting++;
00848 else if (strstr(ptr, "}") || strstr(ptr, "]")) subnesting--;
00849 else if (!strcmp(ptr, "point")) continue;
00850 else {
00851 float u, v;
00852 u = atof(ptr);
00853 ptr = get_next_token(buffer, bufsize, fp);
00854 v = atof(ptr);
00855
00856
00857 texture_u.Append(u); texture_v.Append(v);
00858
00859
00860
00861 if (strstr(ptr, "}") || strstr(ptr, "]")) subnesting--;
00862 }
00863
00864
00865 } while (subnesting > 0);
00866 cerr << "...read " << texture_u.NumElements() << " texture coords\n";
00867 }
00868 else if (!strcmp(ptr, "textureIndex")) {
00869 ptr = get_next_token(buffer, bufsize, fp);
00870
00871 int index = last_block_of_coords_index;
00872 ptr = get_next_token(buffer, bufsize, fp);
00873 while (!strstr(ptr, "}") && !strstr(ptr, "]")) {
00874 float u, v;
00875 u = atof(ptr);
00876 ptr = get_next_token(buffer, bufsize, fp);
00877 v = atof(ptr);
00878 ptr = get_next_token(buffer, bufsize, fp);
00879
00880
00881 Node* n = nodearray.getNode(index);
00882 if (n) {
00883 n->setTextureCoords(u, v);
00884 cerr << "setting node " << index << " texture coords to " << u << ", " << v << endl;
00885 }
00886
00887
00888 index++;
00889 ptr = get_next_token(buffer, bufsize, fp);
00890 }
00891 }
00892 else if (!strcmp(ptr, "textureCoordIndex")) {
00893
00894 int face_index = 0, subnesting = 0;
00895 do {
00896 ptr = get_next_token(buffer, bufsize, fp);
00897
00898 if (strstr(ptr, "{") || strstr(ptr, "[")) { subnesting++; continue; }
00899 if (strstr(ptr, "}") || strstr(ptr, "]")) { subnesting--; continue; }
00900
00901
00902 Face* f = facearray.getFace(face_index);
00903 if (!f) { cerr << "textureCoordIndex: bad face index=" << face_index << endl; continue; }
00904
00905
00906 for (int i=0; i<3; i++) {
00907 int index = atoi(ptr);
00908 if ((index < 0) || (index >= texture_u.NumElements())) {
00909 cerr << "textureCoordIndex: index " << index << " out of bounds\n";
00910 continue;
00911 }
00912 float u = texture_u[index], v = texture_v[index];
00913 Node* n = f->getNodeLink(i);
00914 if (!n) continue;
00915 n->setTextureCoords(u, v);
00916
00917
00918 ptr = get_next_token(buffer, bufsize, fp);
00919 if (strstr(ptr, "}") || strstr(ptr, "]")) { subnesting--; continue; }
00920 }
00921
00922 face_index++;
00923 } while (subnesting > 0);
00924 }
00925 else if (!strcmp(ptr, "Normal")) {
00926 int subnesting = 0;
00927 do {
00928 ptr = get_next_token(buffer, bufsize, fp);
00929 if (strstr(ptr, "{") || strstr(ptr, "[")) subnesting++;
00930 else if (strstr(ptr, "}") || strstr(ptr, "]")) subnesting--;
00931
00932 } while (subnesting > 0);
00933 }
00934 else if (!strcmp(ptr, "normalIndex")) {
00935 do {
00936 ptr = get_next_token(buffer, bufsize, fp);
00937 } while (!strstr(ptr, "]"));
00938 }
00939 else if (!strcmp(ptr, "MaterialBinding")) {
00940 do {
00941 ptr = get_next_token(buffer, bufsize, fp);
00942 } while (!strstr(ptr, "}"));
00943 }
00944 else if (!strcmp(ptr, "Material")) {
00945 ptr = get_next_token(buffer, bufsize, fp);
00946
00947
00948 do {
00949 ptr = get_next_token(buffer, bufsize, fp);
00950
00951
00952 if (!strcmp(ptr, "ambientColor")) {
00953 double r,g,b;
00954 ptr = get_next_token(buffer, bufsize, fp); r = atof(ptr);
00955 ptr = get_next_token(buffer, bufsize, fp); g = atof(ptr);
00956 ptr = get_next_token(buffer, bufsize, fp); b = atof(ptr);
00957 setAmbientColor(r,g,b,1.0);
00958 }
00959 else if (!strcmp(ptr, "diffuseColor")) {
00960 double r,g,b;
00961 ptr = get_next_token(buffer, bufsize, fp); r = atof(ptr);
00962 ptr = get_next_token(buffer, bufsize, fp); g = atof(ptr);
00963 ptr = get_next_token(buffer, bufsize, fp); b = atof(ptr);
00964 setDiffuseColor(r,g,b,1.0);
00965 }
00966 else if (!strcmp(ptr, "emissiveColor")) {
00967 double r,g,b;
00968 ptr = get_next_token(buffer, bufsize, fp); r = atof(ptr);
00969 ptr = get_next_token(buffer, bufsize, fp); g = atof(ptr);
00970 ptr = get_next_token(buffer, bufsize, fp); b = atof(ptr);
00971
00972 setDiffuseColor(r,g,b,1.0);
00973 }
00974 else if (!strcmp(ptr, "specularColor")) {
00975 double r,g,b;
00976 ptr = get_next_token(buffer, bufsize, fp); r = atof(ptr);
00977 ptr = get_next_token(buffer, bufsize, fp); g = atof(ptr);
00978 ptr = get_next_token(buffer, bufsize, fp); b = atof(ptr);
00979 setSpecularColor(r,g,b,1.0);
00980 }
00981 else if (!strcmp(ptr, "shininess")) {
00982 double s;
00983 ptr = get_next_token(buffer, bufsize, fp); s = atof(ptr);
00984 if (s <= 1.0) s *= 128;
00985 setShininess(s);
00986 }
00987 else if (!strcmp(ptr, "transparency")) {
00988
00989
00990
00991 double a;
00992 ptr = get_next_token(buffer, bufsize, fp); a = atof(ptr);
00993
00994 a = 1.0 - a;
00995 float* cur_diffuse = getDiffuseColor();
00996 setDiffuseColor(cur_diffuse[0], cur_diffuse[1], cur_diffuse[2],a);
00997 }
00998 else if (debug)
00999 cerr << "Material: UNKNOWN ATTRIBUTE: " << ptr << endl;
01000 } while (!strstr(ptr, "}"));
01001
01002
01003 }
01004 else if (!strcmp(ptr, "Texture2")) {
01005 ptr = get_next_token(buffer, bufsize, fp);
01006 ptr = get_next_token(buffer, bufsize, fp);
01007
01008 ptr = get_next_token(buffer, bufsize, fp);
01009 if (*ptr == '\"') { ptr++; ptr[strlen(ptr)-1] = '\0'; }
01010
01011
01012 if (!getTexture()) {
01013 cerr << getName() << ": reading texture from file [" << ptr << "]\n";
01014 debug = 1;
01015 setTexture(ptr);
01016 debug = 0;
01017 }
01018
01019 if (!getTexture())
01020 cerr << getName() << ": could not read texture\n";
01021
01022 ptr = get_next_token(buffer, bufsize, fp);
01023 }
01024 else if (strstr(ptr, "Texture2Transform")) {
01025 do {
01026 ptr = get_next_token(buffer, bufsize, fp);
01027 } while (!strstr(ptr, "}"));
01028 }
01029 else if (!strcmp(ptr, "Translation")) {
01030 local_trans_nest_level = nesting;
01031 ptr = get_next_token(buffer, bufsize, fp);
01032
01033
01034 ptr = get_next_token(buffer, bufsize, fp);
01035 while (!strstr(ptr, "}") && !strstr(ptr, "]")) {
01036 if (!strcmp(ptr, "translation")) {
01037 double x,y,z;
01038 ptr = get_next_token(buffer, bufsize, fp); x = atof(ptr);
01039 ptr = get_next_token(buffer, bufsize, fp); y = atof(ptr);
01040 ptr = get_next_token(buffer, bufsize, fp); z = atof(ptr);
01041 local_xform.m[3][0] = x; local_xform.m[3][1] = y; local_xform.m[3][2] = z;
01042 }
01043 ptr = get_next_token(buffer, bufsize, fp);
01044 }
01045
01046
01047 }
01048 else if (!strcmp(ptr, "Rotation")) {
01049 local_rot_nest_level = nesting;
01050 ptr = get_next_token(buffer, bufsize, fp);
01051
01052
01053 ptr = get_next_token(buffer, bufsize, fp);
01054 while (!strstr(ptr, "}") && !strstr(ptr, "]")) {
01055 if (!strcmp(ptr, "rotation")) {
01056 double x,y,z,t;
01057 ptr = get_next_token(buffer, bufsize, fp); x = atof(ptr);
01058 ptr = get_next_token(buffer, bufsize, fp); y = atof(ptr);
01059 ptr = get_next_token(buffer, bufsize, fp); z = atof(ptr);
01060 ptr = get_next_token(buffer, bufsize, fp); t = atof(ptr);
01061
01062
01063
01064
01065 }
01066 ptr = get_next_token(buffer, bufsize, fp);
01067 }
01068
01069
01070 }
01071 else if (!strcmp(ptr, "Scaling")) {
01072 local_scale_nest_level = nesting;
01073 ptr = get_next_token(buffer, bufsize, fp);
01074
01075
01076 ptr = get_next_token(buffer, bufsize, fp);
01077 while (!strstr(ptr, "}") && !strstr(ptr, "]")) {
01078 if (!strcmp(ptr, "scaling")) {
01079 double x,y,z;
01080 ptr = get_next_token(buffer, bufsize, fp); x = atof(ptr);
01081 ptr = get_next_token(buffer, bufsize, fp); y = atof(ptr);
01082 ptr = get_next_token(buffer, bufsize, fp); z = atof(ptr);
01083 local_xform.m[0][0] = x; local_xform.m[1][1] = y; local_xform.m[2][2] = z;
01084 }
01085 ptr = get_next_token(buffer, bufsize, fp);
01086 }
01087
01088 ptr = get_next_token(buffer, bufsize, fp);
01089 }
01090 else if (!strcmp(ptr, "MatrixTransform")) {
01091 local_rot_nest_level = nesting;
01092 ptr = get_next_token(buffer, bufsize, fp);
01093
01094
01095 ptr = get_next_token(buffer, bufsize, fp);
01096 while (!strstr(ptr, "}")) {
01097 if (!strcmp(ptr, "matrix")) {
01098 double m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44;
01099
01100 ptr = get_next_token(buffer, bufsize, fp); m11 = atof(ptr);
01101 ptr = get_next_token(buffer, bufsize, fp); m12 = atof(ptr);
01102 ptr = get_next_token(buffer, bufsize, fp); m13 = atof(ptr);
01103 ptr = get_next_token(buffer, bufsize, fp); m14 = atof(ptr);
01104 ptr = get_next_token(buffer, bufsize, fp); m21 = atof(ptr);
01105 ptr = get_next_token(buffer, bufsize, fp); m22 = atof(ptr);
01106 ptr = get_next_token(buffer, bufsize, fp); m23 = atof(ptr);
01107 ptr = get_next_token(buffer, bufsize, fp); m24 = atof(ptr);
01108 ptr = get_next_token(buffer, bufsize, fp); m31 = atof(ptr);
01109 ptr = get_next_token(buffer, bufsize, fp); m32 = atof(ptr);
01110 ptr = get_next_token(buffer, bufsize, fp); m33 = atof(ptr);
01111 ptr = get_next_token(buffer, bufsize, fp); m34 = atof(ptr);
01112 ptr = get_next_token(buffer, bufsize, fp); m41 = atof(ptr);
01113 ptr = get_next_token(buffer, bufsize, fp); m42 = atof(ptr);
01114 ptr = get_next_token(buffer, bufsize, fp); m43 = atof(ptr);
01115 ptr = get_next_token(buffer, bufsize, fp); m44 = atof(ptr);
01116
01117
01118 local_xform.m[0][0] = m11; local_xform.m[0][1] = m12; local_xform.m[0][2] = m13;
01119 local_xform.m[1][0] = m21; local_xform.m[1][1] = m22; local_xform.m[1][2] = m23;
01120 local_xform.m[2][0] = m31; local_xform.m[2][1] = m32; local_xform.m[2][2] = m33;
01121 local_xform.m[3][0] = m41; local_xform.m[3][1] = m42; local_xform.m[3][2] = m43;
01122 }
01123 ptr = get_next_token(buffer, bufsize, fp);
01124 }
01125
01126
01127 }
01128 else {
01129 if (debug) cerr << "UNKNOWN TOKEN: " << ptr << endl;
01130
01131 }
01132
01133
01134 if (nesting < local_rot_nest_level) local_xform.Init();
01135
01136 }
01137 }
01138
01139
01140 cerr << *this << ", " << cur_part_id << " subparts\n";
01141 cerr << "final nesting level was " << nesting << endl;
01142
01143
01144 nodearray.computeStats();
01145
01146
01147 facearray.computeNormals();
01148
01149
01150 nodearray.interpolateNormals();
01151
01152
01153
01154
01155 return(status);
01156 }
01157
01158 GSPEC *gs = NULL;
01159 int vertex_is_void(Point3D p)
01160 {
01161 if ((p.x == -1) || (p.y == -1) || (p.z == -1)) return(1);
01162 else return(0);
01163 }
01164
01165
01166
01167
01168 int Object::ReadCyberware(FILE* fp)
01169 {
01170 if (debug)
01171 cerr << "Object[" << name << "]::ReadCyberware(" << fp << ")\n";
01172
01173
01174 nodearray.reset();
01175 edgearray.reset();
01176 facearray.reset();
01177
01178
01179 if ((gs = cyread(NULL, _fileno(fp))) == NULL)
01180 return(0);
01181
01182
01183 int is_cartesian = ((gs->flags & FLAG_CARTESIAN) > 0);
01184 int lg_size = gs->lgmax - gs->lgmin + 1;
01185 int lt_size = gs->ltmax - gs->ltmin + 1;
01186
01187
01188 {
01189 fprintf(stderr, "image: %s ", gs->name);
01190 fprintf(stderr, "hdrsiz=%d ltincr=%ld\n", sizeof(GSPEC), gs->ltincr);
01191 fprintf(stderr, "ltrange=%d:%d lgrange=%d:%d\n",
01192 gs->ltmin, gs->ltmax, gs->lgmin, gs->lgmax);
01193 fprintf(stderr, "coord type=%d (0=cyl, 1=cartesian)\n", is_cartesian);
01194 }
01195
01196
01197 int projected_num_nodes = lg_size * lt_size;
01198 int projected_num_edges = 3 * projected_num_nodes;
01199 int projected_num_faces = 2 * projected_num_nodes;
01200 nodearray.allocateNodes(projected_num_nodes);
01201 edgearray.allocateEdges(projected_num_edges);
01202 facearray.allocateFaces(projected_num_faces);
01203
01204
01205 long theta = gs->lgmin * gs->lgincr;
01206 int num_good_nodes = 0, num_void_nodes = 0;
01207 for (int lg = gs->lgmin; lg <= gs->lgmax; lg++, theta += gs->lgincr) {
01208 long y = gs->ltmin * gs->ltincr;
01209
01210
01211 float cos_theta = cos(URTOR(theta));
01212 float sin_theta = sin(URTOR(theta));
01213
01214
01215 for (int lt = gs->ltmin; lt <= gs->ltmax; lt++, y += gs->ltincr) {
01216 long radius = GETR(gs, lt, lg);
01217
01218
01219 if (radius == long(VOIDGS(gs))) {
01220 num_void_nodes++;
01221 nodearray.addNode( Point3D(-1,-1,-1) );
01222 continue;
01223 }
01224
01225
01226 Point3D pt;
01227 if (is_cartesian) {
01228 pt = Point3D(theta,y,radius);
01229 } else {
01230 long x, z;
01231 x = long(sin_theta * radius);
01232 z = -long(cos_theta * radius);
01233 pt = Point3D(x,y,z);
01234 }
01235 num_good_nodes++;
01236
01237
01238 const double microns_to_millimeters = 1000.0;
01239 int index = nodearray.addNode( pt/microns_to_millimeters );
01240
01241
01242 Node* new_node = nodearray.getNode(index);
01243 new_node->setTextureCoords(
01244 double(lt-gs->ltmin)/lt_size,
01245 double(lg-gs->lgmin)/lg_size);
01246 }
01247 }
01248 cyfree(gs);
01249
01250
01251 cerr << "Had " << num_good_nodes << " good nodes and "
01252 << num_void_nodes << " void nodes\n";
01253
01254
01255 cerr << "Centering object\n";
01256 CenterObject();
01257 cerr << "done Centering object\n";
01258
01259
01260 cerr << "Generating mesh\n";
01261 int num_polys = 0, num_void_polys = 0;
01262 {
01263 const int ypass = (gs->ltmax - gs->ltmin + 1);
01264 const int xpass = (gs->lgmax - gs->lgmin + 1);
01265 int num_verts = nodearray.getNumNodes();
01266 for (int x=0; x<(num_verts/xpass)-1; x++)
01267 for (int y=0; y<ypass-1; y++) {
01268 int index = x * ypass + y;
01269 int index2 = (x+1) * ypass + y;
01270
01271
01272 Node* n_a = nodearray.getNode(index);
01273 Node* n_b = nodearray.getNode(index+1);
01274 Node* n_c = nodearray.getNode(index2);
01275 Node* n_d = nodearray.getNode(index2+1);
01276 if (vertex_is_void(n_a->p) || vertex_is_void(n_b->p) ||
01277 vertex_is_void(n_c->p) || vertex_is_void(n_d->p)) {
01278 num_void_polys++;
01279 continue;
01280 }
01281
01282
01283 facearray.addFace(index, index2, index+1);
01284 num_polys++;
01285
01286
01287 facearray.addFace(index+1, index2, index2+1);
01288 num_polys++;
01289 }
01290 }
01291 cerr << "done Generating mesh\n";
01292
01293
01294 cerr << "Had " << num_polys << " good polys and "
01295 << num_void_polys << " void polygons\n";
01296
01297
01298 dynamics = deformable;
01299 set_default_material_properties();
01300 setDiffuseColor(1.0, 1.0, 1.0, 1.0);
01301 type = faces_only;
01302
01303
01304
01305
01306 #ifdef TESTING_NEW_TEXTURE_COORDS
01307
01308 if (is_cartesian)
01309 nodearray.computeTextureCoords(Node::linear);
01310 else nodearray.computeTextureCoords(Node::cylindrical);
01311 #endif
01312
01313
01314 facearray.computeNormals();
01315
01316
01317 nodearray.interpolateNormals();
01318
01319
01320 return(1);
01321 }
01322
01323 int Object::Read(char* dirname_part, char* filename_part)
01324 {
01325
01326 char filename[256];
01327 sprintf(filename, "%s/%s", dirname_part, filename_part);
01328
01329
01330 setPath(dirname_part);
01331
01332
01333 return Read(filename);
01334 }
01335
01336 int Object::Read(char* filename) {
01337 if (debug) cerr << "Object[" << name << "]::Read(" << filename << ")\n";
01338
01339
01340 FILE* meshfile;
01341 if ((meshfile = fopen(filename, "r")) == NULL) {
01342 printf("Could not open node data file\n");
01343 return(0);
01344 }
01345
01346
01347 char* ext = myextension(filename);
01348 if (!strcmp(ext, ".mesh")) ReadMesh(meshfile);
01349 else if (!strcmp(ext, ".smf")) ReadSMF(meshfile);
01350 else if (!strcmp(ext, ".obj")) ReadOBJ(meshfile);
01351 else if (!strcmp(ext, ".cy")) ReadCyberware(meshfile);
01352 else if (!strcmp(ext, ".frd")) ReadFRD(meshfile);
01353 else if (!strcmp(ext, ".wrl")) ReadVRML(meshfile);
01354 else if (!strcmp(ext, ".iv")) ReadVRML(meshfile);
01355 else if (!strcmp(ext, ".inp")) ReadAmira(meshfile);
01356 else if (!strcmp(ext, ".sobj")) ReadSOBJ(meshfile);
01357
01358
01359 fclose(meshfile);
01360
01361
01362 dl_needs_refresh = 1;
01363
01364
01365 return(0);
01366 }
01367
01368 void Object::ParseAttribute(char* buffer)
01369 {
01370
01371 int had_bambient = 0;
01372 int had_bdiffuse = 0;
01373 int had_bspecular = 0;
01374
01375
01376 char attr_name[80]; sscanf(buffer, "%s", attr_name);
01377 cerr << " " << attr_name << " [";
01378
01379
01380 if (!strcmp(attr_name, "ambient:")) {
01381 float r,g,b,a;
01382 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01383 setAmbientColor(r,g,b,a);
01384 if (!had_bambient) setBackAmbientColor(r,g,b,a);
01385 cerr << r << "," << g << "," << b << "," << a;
01386 }
01387 else if (!strcmp(attr_name, "bambient:")) {
01388 float r,g,b,a;
01389 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01390 setBackAmbientColor(r,g,b,a);
01391 cerr << r << "," << g << "," << b << "," << a;
01392 had_bambient = 1;
01393 }
01394 else if (!strcmp(attr_name, "diffuse:")) {
01395 float r,g,b,a;
01396 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01397 setDiffuseColor(r,g,b,a);
01398 if (!had_bdiffuse) setBackDiffuseColor(r,g,b,a);
01399 cerr << r << "," << g << "," << b << "," << a;
01400 }
01401 else if (!strcmp(attr_name, "bdiffuse:")) {
01402 float r,g,b,a;
01403 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01404 setBackDiffuseColor(r,g,b,a);
01405 cerr << r << "," << g << "," << b << "," << a;
01406 had_bdiffuse = 1;
01407 }
01408 else if (!strcmp(attr_name, "specular:")) {
01409 float r,g,b,a;
01410 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01411 setSpecularColor(r,g,b,a);
01412 if (!had_bspecular) setBackSpecularColor(r,g,b,a);
01413 cerr << r << "," << g << "," << b << "," << a;
01414 }
01415 else if (!strcmp(attr_name, "bspecular:")) {
01416 float r,g,b,a;
01417 sscanf(buffer, "%*s %f %f %f %f", &r, &g, &b, &a);
01418 setBackSpecularColor(r,g,b,a);
01419 cerr << r << "," << g << "," << b << "," << a;
01420 had_bspecular = 1;
01421 }
01422 else if (!strcmp(attr_name, "shininess:")) {
01423 float s;
01424 sscanf(buffer, "%*s %f", &s);
01425 setShininess(s);
01426 cerr << s;
01427 }
01428 else if (!strcmp(attr_name, "bshininess:")) {
01429 float s;
01430 sscanf(buffer, "%*s %f", &s);
01431 setBackShininess(s);
01432 cerr << s;
01433 }
01434 else if (!strcmp(attr_name, "texture:")) {
01435 char texturefilename[256];
01436 sscanf(buffer, "%*s %s", texturefilename);
01437 setTexture(texturefilename);
01438 cerr << texturefilename;
01439 }
01440 else if (!strcmp(attr_name, "texturecoords:")) {
01441 int model;
01442 sscanf(buffer, "%*s %d", &model);
01443 setTextureCoords(Node::texture_coord_type(model));
01444 cerr << model;
01445 }
01446 else if (!strcmp(attr_name, "behavior:")) {
01447 char str[80];
01448 sscanf(buffer, "%*s %s", str);
01449 behavior_type b = none;
01450 if (!strcmp(str, "none")) b = none;
01451 else if (!strcmp(str, "grabbing")) b = grabbing;
01452 else if (!strcmp(str, "cutting")) b = cutting;
01453 else if (!strcmp(str, "deleting")) b = deleting;
01454 else if (!strcmp(str, "poking")) b = poking;
01455 else if (!strcmp(str, "ablating")) b = ablating;
01456 else if (!strcmp(str, "cauterizing")) b = cauterizing;
01457 else if (!strcmp(str, "dilating")) b = dilating;
01458 else if (!strcmp(str, "coloring")) b = coloring;
01459 else if (!strcmp(str, "quisar_test")) b = quisar_test;
01460 else if (!strcmp(str, "beating")) b = beating;
01461 else if (!strcmp(str, "fluid")) b = fluid;
01462 else {
01463 int val = atoi(str);
01464 switch (val) {
01465 case int(none): b = none; break;
01466 case int(grabbing): b = grabbing; break;
01467 case int(cutting): b = cutting; break;
01468 case int(deleting): b = deleting; break;
01469 case int(poking): b = poking; break;
01470 case int(ablating): b = ablating; break;
01471 case int(cauterizing): b = cauterizing; break;
01472 case int(dilating): b = dilating; break;
01473 case int(coloring): b = coloring; break;
01474 case int(quisar_test): b = quisar_test; break;
01475 case int(beating): b = beating; break;
01476 case int(fluid): b = fluid; break;
01477 }
01478 }
01479 setBehavior(b);
01480 cerr << b;
01481 }
01482 else if (!strcmp(attr_name, "dynamics:")) {
01483 char str[80];
01484 sscanf(buffer, "%*s %s", str);
01485 dynamics_type d = rest;
01486 if (!strcmp(str, "rest")) d = rest;
01487 else if (!strcmp(str, "rigid")) d = rigid;
01488 else if (!strcmp(str, "deformable")) d = deformable;
01489 else if (!strcmp(str, "articulate")) d = articulate;
01490 else if (!strcmp(str, "button")) d = button;
01491 else {
01492 int val = atoi(str);
01493 switch (val) {
01494 case 0: d = rest; break;
01495 case 1: d = rigid; break;
01496 case 2: d = deformable; break;
01497 case 3: d = articulate; break;
01498 case 4: d = button; break;
01499 }
01500 }
01501 setDynamics(d);
01502 cerr << d;
01503 }
01504 else if (!strcmp(attr_name, "mass:")) {
01505 float m;
01506 sscanf(buffer, "%*s %f", &m);
01507 getNodeArray()->setMasses(m);
01508 cerr << m;
01509 }
01510 else if (!strcmp(attr_name, "deformonlyongrab:")) {
01511 int i;
01512 sscanf(buffer, "%*s %d", &i);
01513 do_deform_only_on_grab = i;
01514 cerr << i;
01515 }
01516 else if (!strcmp(attr_name, "springconstant:")) {
01517 float sc;
01518 sscanf(buffer, "%*s %f", &sc);
01519 getEdgeArray()->setSpringConstants(sc);
01520 cerr << sc;
01521 }
01522 else if (!strcmp(attr_name, "dampconstant:")) {
01523 float dc;
01524 sscanf(buffer, "%*s %f", &dc);
01525 getNodeArray()->setVelocityDampConstants(dc);
01526 cerr << dc;
01527 }
01528 else if (!strcmp(attr_name, "nummethod:")) {
01529 int nm;
01530 sscanf(buffer, "%*s %d", &nm);
01531 setNumMethod(Object::numerical_method(nm));
01532 cerr << nm;
01533 }
01534 else if (!strcmp(attr_name, "visible:")) {
01535 int on;
01536 sscanf(buffer, "%*s %d", &on);
01537 SetVisible(on);
01538 cerr << on;
01539 }
01540 else if (!strcmp(attr_name, "translate:")) {
01541 float x, y, z;
01542 sscanf(buffer, "%*s %f %f %f", &x, &y, &z);
01543 Point3D vector(x,y,z);
01544 Move(vector);
01545 cerr << x << " " << y << " " << z;
01546 }
01547 else if (!strcmp(attr_name, "scale:")) {
01548 float scale_factor;
01549 sscanf(buffer, "%*s %f", &scale_factor);
01550 Scale(scale_factor);
01551 cerr << scale_factor;
01552 }
01553 else if (!strcmp(attr_name, "rotate:")) {
01554 char axis; double angle;
01555 sscanf(buffer, "%*s %c %lf", &axis, &angle);
01556 Rotate(axis, angle);
01557 cerr << axis << " " << angle;
01558 }
01559 else if (!strcmp(attr_name, "collisionextent:")) {
01560 int ce;
01561 sscanf(buffer, "%*s %d", &ce);
01562 setCollisionExtent(Object::collision_extent_type(ce));
01563 cerr << ce;
01564 }
01565 else if (!strcmp(attr_name, "linkedpart:")) {
01566 int lp;
01567 sscanf(buffer, "%*s %d", &lp);
01568 setLinkedPart(lp);
01569 cerr << lp;
01570 }
01571 else if (!strcmp(attr_name, "hingenode:")) {
01572 int i;
01573 int si;
01574 float x,y,z;
01575 double maxopen, maxclosed;
01576 int col0 = -1;
01577 int col1 = -1;
01578 int col2 = -1;
01579
01580 sscanf(buffer, "%*s %d %d %f %f %f %lf %lf %d %d %d",
01581 &si, &i, &x, &y, &z, &maxopen, &maxclosed,
01582 &col0, &col1, &col2);
01583 Point3D r(x,y,z);
01584 this->addToHinges(si,i,r,maxopen,maxclosed,col0,col1,col2);
01585
01586 cerr << si << " " << i << " " << r << " " << maxopen << " "
01587 << maxclosed << " " << col0 << " " << col1 << " " << col2;
01588 }
01589 else if (!strcmp(attr_name, "sensoroffset:")) {
01590 float x,y,z;
01591 sscanf(buffer, "%*s %f %f %f", &x, &y, &z);
01592 Point3D p(x,y,z);
01593 setSensorOffset(p);
01594 cerr << p;
01595 }
01596 else if (!strcmp(attr_name, "tipnode:")) {
01597 int tn;
01598 sscanf(buffer, "%*s %d", &tn);
01599 setTip(tn);
01600 cerr << tn;
01601 }
01602 else if (!strcmp(attr_name, "collisionfaces:")) {
01603
01604
01605
01606 char* delimiters = " \t";
01607
01608 char* ptr = strtok(buffer, delimiters);
01609
01610
01611
01612
01613
01614 while ((ptr = strtok(NULL, delimiters)) != NULL ) {
01615
01616 int face_index = atoi(ptr);
01617
01618 Face* face = getFaceArray()->getFace(face_index);
01619
01620 if (!face) {
01621
01622 cerr << "Bad collision face index: " << face_index << endl;
01623
01624 }
01625
01626 else {
01627
01628
01629
01630 collision_faces.Append(face);
01631
01632 }
01633
01634 }
01635
01636 }
01637 else if (!strcmp(attr_name, "cuttingfaces:")) {
01638 char* delimiters = " \t\n";
01639 char* ptr = strtok(buffer, delimiters);
01640 while(ptr) {
01641 ptr = strtok(NULL,delimiters);
01642 if (ptr == NULL) break;
01643 int f = atoi(ptr);
01644 cerr << f << " " ;
01645 addToCuttingFaces(getFaceArray()->getFace(f));
01646 }
01647 }
01648 else if (!strcmp(attr_name, "cuttingedges:")) {
01649 char* delimiters = " \t\n";
01650 char* ptr = strtok(buffer, delimiters);
01651 while(ptr) {
01652 ptr = strtok(NULL,delimiters);
01653 if (ptr == NULL) break;
01654 int e = atoi(ptr);
01655 cerr << e << " " ;
01656 addToCuttingEdges(getEdgeArray()->getEdge(e));
01657 }
01658 }
01659 else {
01660 cerr << "UNKNOWN ATTRIBUTE";
01661 }
01662
01663
01664 cerr << "]\n";
01665 }
01666
01667 void Object::addToHinges(int si, int ai, Point3D r, double maxopen, double maxclosed,
01668 int col0, int col1, int col2)
01669 {
01670 hinge h;
01671 h.sensor_index = si;
01672 h.node_index = ai;
01673 h.rotation_vector = r;
01674 h.max_open = maxopen;
01675 h.max_closed = maxclosed;
01676
01677 int posnum = 0;
01678 int negnum = 0;
01679
01680 for (int i=0; i<3; i++) {
01681 h.colors_pos[i] = -1;
01682 h.colors_neg[i] = -1;
01683 }
01684
01685
01686 if (col0 > -1) {
01687 h.colors_pos[posnum] = col0;
01688 posnum++;
01689 }
01690 else {
01691 h.colors_neg[negnum] = col0;
01692 negnum++;
01693 }
01694
01695 if (col1 > -1) {
01696 h.colors_pos[posnum] = col1;
01697 posnum++;
01698 }
01699 else {
01700 h.colors_neg[negnum] = col1;
01701 negnum++;
01702 }
01703
01704 if (col2 > -1) {
01705 h.colors_pos[posnum] = col2;
01706 posnum++;
01707 }
01708 else {
01709 h.colors_neg[negnum] = col2;
01710 negnum++;
01711 }
01712
01713 hinges.Append(h);
01714 return;
01715 }
01716
01717 void Object::setAmbientColor(float red, float green, float blue, float alpha)
01718 {
01719
01720 mat_ambient[0] = red;
01721 mat_ambient[1] = green;
01722 mat_ambient[2] = blue;
01723 mat_ambient[3] = alpha;
01724
01725
01726 dl_needs_refresh = 1;
01727 }
01728
01729 void Object::setDiffuseColor(float red, float green, float blue, float alpha)
01730 {
01731 #ifdef SUN
01732
01733
01734
01735
01736 if (texture) {
01737 red = green = blue = alpha;
01738 }
01739 #endif
01740
01741
01742 mat_diffuse[0] = red;
01743 mat_diffuse[1] = green;
01744 mat_diffuse[2] = blue;
01745 mat_diffuse[3] = alpha;
01746
01747
01748 dl_needs_refresh = 1;
01749 }
01750
01751 void Object::setSpecularColor(float red, float green, float blue, float alpha)
01752 {
01753
01754 mat_specular[0] = red;
01755 mat_specular[1] = green;
01756 mat_specular[2] = blue;
01757 mat_specular[3] = alpha;
01758
01759
01760 dl_needs_refresh = 1;
01761 }
01762
01763 void Object::setShininess(float s)
01764 {
01765
01766 mat_shininess[0] = s;
01767
01768
01769 dl_needs_refresh = 1;
01770 }
01771
01772 void Object::setBackAmbientColor(float red, float green, float blue, float alpha)
01773 {
01774
01775 back_mat_ambient[0] = red;
01776 back_mat_ambient[1] = green;
01777 back_mat_ambient[2] = blue;
01778 back_mat_ambient[3] = alpha;
01779
01780
01781 dl_needs_refresh = 1;
01782 }
01783
01784 void Object::setBackDiffuseColor(float red, float green, float blue, float alpha)
01785 {
01786
01787
01788
01789
01790 if (texture) {
01791 red = green = blue = alpha;
01792 }
01793
01794
01795 back_mat_diffuse[0] = red;
01796 back_mat_diffuse[1] = green;
01797 back_mat_diffuse[2] = blue;
01798 back_mat_diffuse[3] = alpha;
01799
01800
01801 dl_needs_refresh = 1;
01802 }
01803
01804 void Object::setBackSpecularColor(float red, float green, float blue, float alpha)
01805 {
01806
01807 back_mat_specular[0] = red;
01808 back_mat_specular[1] = green;
01809 back_mat_specular[2] = blue;
01810 back_mat_specular[3] = alpha;
01811
01812
01813 dl_needs_refresh = 1;
01814 }
01815
01816 void Object::setBackShininess(float s)
01817 {
01818
01819 back_mat_shininess[0] = s;
01820
01821
01822 dl_needs_refresh = 1;
01823 }
01824
01825
01826
01827 void Object::setTexture(char* filename)
01828 {
01829 char texture_filename[256];
01830 if (filename)
01831 strncpy(texture_filename, filename, 256);
01832 else {
01833 char regular_filename[256];
01834 char* filePath = getPath();
01835
01836 if (strcmp(getPath(), "")) {
01837 sprintf(regular_filename, "%s/%s", getPath(), getName());
01838 }
01839 else {
01840 sprintf(regular_filename, "%s", getName());
01841 }
01842 strncpy(texture_filename, regular_filename, 256);
01843 char* ptr = myrindex(texture_filename, '.');
01844 if (ptr) {
01845 sprintf(ptr, ".rgb");
01846 }
01847 else {
01848 sprintf(texture_filename, "%s.rgb", texture_filename);
01849 }
01850 }
01851
01852
01853
01854
01855 if (debug)
01856 cerr << "Reading texture from file [" << texture_filename << "]\n";
01857
01858
01859 texture = read_texture(texture_filename,
01860 &texture_size.x, &texture_size.y, &texture_size.z);
01861
01862
01863 if (debug) {
01864 if (texture)
01865 cerr << " size = " << texture_size.x << "x" << texture_size.y
01866 << " @ " << texture_size.z << endl;
01867 else cerr << " texture [" << texture_filename << "] not found!\n";
01868 }
01869
01870
01871 dl_needs_refresh = 1;
01872 }
01873
01874 void Object::setTextureCoords(Node::texture_coord_type t)
01875 {
01876 nodearray.computeTextureCoords(t);
01877 dl_needs_refresh = 1;
01878 }
01879
01880 void Object::moveTexture(Point3D translation, Point3D scaling)
01881 {
01882 nodearray.moveTexture(translation, scaling);
01883 dl_needs_refresh = 1;
01884 }
01885
01886 void Object::tipUpdate()
01887 {
01888 if (nodearray.getNumNodes() <= 0) return;
01889
01890 tipdelta = getTip() - oldtip;
01891 oldtip = getTip();
01892 }
01893
01894 void Object::Update()
01895 {
01896 if (debug) cerr << "Object[" << name << "]::Update()\n";
01897
01898
01899
01900 being_modified = 1;
01901
01902
01903
01904
01905
01906 if (sensor_p) {
01907
01908
01909
01910
01911
01912
01913
01914 #define NEW_XFORM_OBJECT_WAY
01915 #ifdef NEW_XFORM_OBJECT_WAY
01916
01917
01918 if (linked_part == -1)
01919 xformHingedObject();
01920 else
01921 xformObject();
01922 #else
01923
01924
01925
01926
01927 if (linked_part == -1) {
01928 xformHingedObject();
01929 }
01930 else if (linked_part == 0) {
01931 nodearray.setToInitialPosition();
01932 nodearray.xformNodesOfPart(-1, sensor_p->m, sensor_offset,
01933 sensor_p->pos);
01934 }
01935 else {
01936
01937
01938
01939 Point3D motion_vector = sensor_p->pos - sensor_p->init_pos;
01940 nodearray.moveNodesOfPart(linked_part, motion_vector, 1);
01941 }
01942 #endif
01943
01944
01945
01946 addEverythingToUpdateList();
01947
01948
01949
01950 dl_needs_refresh = 1;
01951 }
01952
01953
01954
01955 switch (dynamics) {
01956 case rest: {
01957
01958
01959
01960 break;
01961 }
01962
01963 case button: {
01964
01965
01966
01967 break;
01968 }
01969
01970 case rigid: {
01971
01972
01973
01974
01975 if (!sensor_p) {
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985 int nodes_moved = nodearray.updateNodesRigid();
01986
01987
01988
01989 if (nodes_moved) {
01990
01991
01992 addEverythingToUpdateList();
01993
01994
01995 dl_needs_refresh = 1;
01996 }
01997
01998
01999
02000
02001 if (type == edges_only) {
02002 dl_needs_refresh = 1;
02003
02004 }
02005
02006 }
02007 break;
02008 }
02009
02010 case deformable: {
02011
02012 if (do_deform_only_on_grab && !being_grabbed) {
02013 if (nodearray.orderedNodesFlag) {
02014 edgearray.computeNewRestLengths();
02015 nodearray.orderedNodesFlag = 0;
02016 }
02017 break;
02018 }
02019
02020
02021 int nodes_moved = nodearray.updateNodes();
02022
02023
02024 if (nodes_moved) {
02025
02026
02027 addEverythingToUpdateList();
02028
02029
02030 if (do_preserve_volume) {
02031 PreserveVolume();
02032 }
02033
02034 dl_needs_refresh = 1;
02035 }
02036
02037
02038
02039 break;
02040 }
02041
02042 case articulate: {
02043
02044 extern game_enum game_mode;
02045 if (game_mode == knot_game || game_mode == vessel_knot_game) {
02046 nodearray.updateThread();
02047
02048 }
02049 else {
02050
02051
02052 nodearray.updateArticulateEdge();
02053 }
02054
02055
02056
02057
02058 addEverythingToUpdateList();
02059
02060
02061
02062
02063 dl_needs_refresh = 1;
02064
02065 break;
02066 }
02067 }
02068
02069
02070
02071
02072
02073 being_modified = 0;
02074 }
02075
02076
02077 void Object::getPosAngle(Point3D* pos_p, Point3D* rot_p)
02078 {
02079 if (strncmp(name, "plane #", 7))
02080 return;
02081
02082 Node *node0 = nodearray.getNode(0);
02083 Point3D pos = node0->p;
02084 Point3D normal = node0->getNormal();
02085 double dotx = normal.Dot(Point3D(1,0,0));
02086 double doty = normal.Dot(Point3D(0,1,0));
02087 double dotz = normal.Dot(Point3D(0,0,1));
02088 double thetax = (acos(dotx))*(180.0/PI);
02089 double thetay = (acos(doty))*(180.0/PI);
02090 double thetaz = (acos(dotz))*(180.0/PI);
02091
02092 *pos_p = pos;
02093 rot_p->x = thetax;
02094 rot_p->y = thetay;
02095 rot_p->z = thetaz;
02096 }
02097
02098
02099 void Object::SplitColor(Object* tool)
02100 {
02101 if (debug) cerr << "Object::SplitColor(" << tool << ")\n";
02102
02103 if (!strstr(tool->name, "grabby") && !strstr(tool->name, "plane"))
02104 return;
02105
02106
02107 Face *splitting_face = tool->facearray.getFace(0);
02108 nodearray.SplitColor(splitting_face);
02109
02110
02111 dl_needs_refresh = 1;
02112 }
02113
02114 void Object::DeleteNodesOfColor(int color)
02115 {
02116 if (debug) cerr << "Object::DeleteNodeOfColor(" << color << ")\n";
02117 facearray.EraseFacesOfColor(color);
02118 edgearray.DeleteFacelessEdges();
02119
02120 dl_needs_refresh = 1;
02121 }
02122
02123 double Object::distanceToBoundingBox(Point3D pt)
02124 {
02125
02126 Point3D cur_min, cur_max;
02127 getBoundingBox(&cur_min, &cur_max);
02128
02129
02130 if ((pt.x > cur_min.x) && (pt.y > cur_min.y) && (pt.z > cur_min.z) &&
02131 (pt.x < cur_max.x) && (pt.y < cur_max.y) && (pt.z < cur_max.z))
02132 return(0);
02133
02134
02135
02136
02137
02138
02139
02140
02141 double xdist, ydist, zdist;
02142 xdist = ydist = zdist = 0.0;
02143 if (pt.x > cur_max.x)
02144 xdist = pt.x - cur_max.x;
02145 else if (pt.x < cur_min.x)
02146 xdist = cur_min.x - pt.x;
02147 if (pt.y > cur_max.y)
02148 ydist = pt.y - cur_max.y;
02149 else if (pt.y < cur_min.y)
02150 ydist = cur_min.y - pt.y;
02151 if (pt.z > cur_max.z)
02152 zdist = pt.z - cur_max.z;
02153 else if (pt.z < cur_min.z)
02154 zdist = cur_min.z - pt.z;
02155
02156
02157 return(sqrt(xdist*xdist + ydist*ydist + zdist*zdist));
02158 }
02159
02160
02161 void Object::HandleBehavior()
02162 {
02163 if (debug) cerr << "Object[" << getName() << "]::HandleBehavior()\n";
02164
02165
02166 tipUpdate();
02167
02168
02169 HandleInteractiveBehavior();
02170 HandleSpontaneousBehavior();
02171 }
02172
02173
02174 void Object::HandleInteractiveBehavior()
02175 {
02176
02177 if (!sensor_p) {
02178 closest_node = NULL;
02179 return;
02180 }
02181
02182
02183
02184
02185
02186
02187
02188 const double max_distance_to_affect = 250.5;
02189
02190
02191 Point3D haptic_force(0,0,0);
02192 float twist_force = 0, grip_force = 0;
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213 switch (behavior) {
02214 case quisar_test: {
02215
02216 if (sensor_p->type != Sensor::haptic_v2_sensor) break;
02217
02218
02219 Haptic_v2* haptic_p = (Haptic_v2*)sensor_p;
02220
02221
02222 Object* other_obj = NULL;
02223
02224
02225 if (closest_node && (haptic_p->active[0] < 0.5)) {
02226 closest_node->setFixedType(Node::NOT);
02227 being_grabbed = 0;
02228 closest_node->getNodeArray()->getObject()->being_grabbed = 0;
02229 closest_node = NULL;
02230 }
02231
02232
02233 if (!closest_node)
02234 closest_node = objectarray_p->FindClosestUnlinkedNode(getTip());
02235
02236
02237 if (closest_node)
02238 other_obj = closest_node->getNodeArray()->getObject();
02239
02240
02241 if (!closest_node) {
02242 haptic_p->my_space = haptic_p->my_space_v;
02243 haptic_p->points_to_save->erase_all();
02244 break;
02245 }
02246
02247 Point3D vect = getTip() - closest_node->p;
02248
02249 if ((haptic_p->active[0] < 0.5) ||
02250 (vect.Length() > max_distance_to_affect)) {
02251
02252 haptic_p->my_space = haptic_p->my_space_t;
02253 haptic_p->points_to_save->erase_all();
02254 haptic_p->my_space_t->erase_all();
02255 triangle *t;
02256 Face *f;
02257 for(int i=0; i< closest_node->numFaceLinks(); i++) {
02258 f = closest_node->getFaceLink(i);
02259 t = new triangle(f->getNodeLink(0)->p, f->getNodeLink(1)->p,
02260 f->getNodeLink(2)->p, f->getNodeLink(0)->getNormal(),
02261 f->getNodeLink(1)->getNormal(),
02262 f->getNodeLink(2)->getNormal(), (char) 127);
02263 haptic_p->my_space_t->add_new_triangle(t);
02264 }
02265 break;
02266 }
02267
02268
02269
02270 if (!being_grabbed) {
02271
02272 if (other_obj->getNumMethod() == quasi_ordered ||
02273
02274 other_obj->getNumMethod() == euler_ordered) {
02275
02276 other_obj->getNodeArray()->OrderNodes(closest_node);
02277 }
02278 being_grabbed = 1;
02279 other_obj->being_grabbed = 1;
02280 }
02281
02282
02283
02284 closest_node->p = getTip();
02285
02286
02287 closest_node->v = Point3D(0,0,0);
02288
02289
02290
02291 closest_node->setFixedType(Node::POS);
02292
02293
02294
02295
02296 Point3D pttmp;
02297 point *mypoint;
02298 double xmin = ceil((closest_node->p.x - RAYON) / MATRIX) * MATRIX;
02299 double ymin = ceil((closest_node->p.y - RAYON) / MATRIX) * MATRIX;
02300 double zmin = ceil((closest_node->p.z - RAYON) / MATRIX) * MATRIX;
02301
02302 haptic_p->my_space_i->erase_all();
02303
02304 for(double x=xmin; x <= (closest_node->p.x + RAYON); x+=MATRIX) {
02305 for(double y=ymin; y <= (closest_node->p.y + RAYON); y+=MATRIX) {
02306 for(double z=zmin; z <= (closest_node->p.z + RAYON); z+=MATRIX) {
02307
02308 pttmp.x = x; pttmp.y = y; pttmp.z = z;
02309 if((closest_node->p - pttmp).Squared() <= RAYON * RAYON) {
02310 mypoint = haptic_p->points_to_save->isthere(&pttmp);
02311 if(mypoint) {
02312 point *pointcopy;
02313 pointcopy = new point(mypoint);
02314 haptic_p->my_space_i->add_new_point(pointcopy);
02315 }
02316 else {
02317 point *pointcopy;
02318 mypoint = new point(&pttmp, what_force_if(closest_node, &pttmp));
02319 pointcopy = new point(mypoint);
02320 haptic_p->points_to_save->add_new_point(pointcopy);
02321 haptic_p->my_space_i->add_new_point(mypoint);
02322 }
02323 }
02324 }
02325 }
02326 }
02327 haptic_p->my_space = haptic_p->my_space_i;
02328 }
02329
02330 case grabbing: {
02331
02332 Object* other_obj = NULL;
02333 float sensor_activation = sensor_p->active[0];
02334 float prev_sensor_activation = prev_grabbing_activation;
02335 prev_grabbing_activation = sensor_activation;
02336
02337
02338
02339
02340 if ((prev_sensor_activation >= 0.5) && (being_grabbed == 0)) {
02341
02342 break;
02343 }
02344
02345
02346
02347 if (closest_node && (sensor_activation < 0.5)) {
02348 closest_node->setFixedType(Node::NOT);
02349
02350 #ifdef JOEL
02351 int hack_index = closest_node->getIndex();
02352
02353 Object *other_vessel = objectarray_p->findObject("other vessel");
02354 if (other_vessel != NULL) {
02355 Object *left_vessel = objectarray_p->findObject("left vessel");
02356 Object *right_vessel = objectarray_p->findObject("right vessel");
02357
02358 Node* n = left_vessel->nodearray.getNode(hack_index);
02359 n->setFixedType(Node::NOT);
02360 n = right_vessel->nodearray.getNode(hack_index);
02361 n->setFixedType(Node::NOT);
02362 n = other_vessel->nodearray.getNode(hack_index);
02363 n->setFixedType(Node::NOT);
02364 }
02365
02366 #endif
02367
02368
02369
02370
02371 if (being_grabbed == 1) {
02372 being_grabbed = 0;
02373 closest_node->getNodeArray()->getObject()->being_grabbed = 0;
02374 }
02375
02376 closest_node = NULL;
02377 }
02378
02379
02380 if (!closest_node)
02381 closest_node = objectarray_p->FindClosestUnlinkedNode(getTip());
02382
02383
02384 if (closest_node)
02385 other_obj = closest_node->getNodeArray()->getObject();
02386
02387
02388 if (!closest_node) break;
02389
02390
02391 if (closest_node->getTieNode()) {
02392 closest_node = NULL;
02393 break;
02394 }
02395
02396
02397 if (sensor_activation < 0.5) break;
02398
02399
02400 Point3D vect = getTip() - closest_node->p;
02401 if (vect.Length() > max_distance_to_affect) {
02402 closest_node = NULL;
02403 if (debug) cerr << "Too far away to grab\n";
02404 break;
02405 }
02406
02407
02408 if (!being_grabbed) {
02409
02410 if (other_obj->getNumMethod() == quasi_ordered ||
02411
02412 other_obj->getNumMethod() == euler_ordered) {
02413 other_obj->getNodeArray()->OrderNodes(closest_node);
02414 }
02415 being_grabbed = 1;
02416 other_obj->being_grabbed = 1;
02417 }
02418
02419
02420 if (closest_node->getNodeArray()->getObject()->getDynamics() == button) {
02421
02422 break;
02423 }
02424
02425
02426
02427
02428 closest_node->p_old = closest_node->p;
02429
02430
02431 closest_node->p = getTip();
02432
02433
02434 closest_node->v = Point3D(0,0,0);
02435
02436
02437
02438 closest_node->setFixedType(Node::POS);
02439
02440 #ifdef JOEL
02441
02442 Object *other_vessel = objectarray_p->findObject("other vessel");
02443 if (other_vessel != NULL) {
02444 Object *left_vessel = objectarray_p->findObject("left vessel");
02445 Object *right_vessel = objectarray_p->findObject("right vessel");
02446
02447 Point3D disp =closest_node->p - closest_node->init_pos;
02448 int hack_index = closest_node->getIndex();
02449 Node* n = left_vessel->nodearray.getNode(hack_index);
02450 n->p = n->init_pos + disp;
02451 n->v = Point3D(0.0,0.0,0.0);
02452 n->setFixedType(Node::POS);
02453 n = right_vessel->nodearray.getNode(hack_index);
02454 n->p = n->init_pos + disp;
02455 n->v = Point3D(0.0,0.0,0.0);
02456 n->setFixedType(Node::POS);
02457 n = other_vessel->nodearray.getNode(hack_index);
02458 n->p = n->init_pos + disp;
02459 n->v = Point3D(0.0,0.0,0.0);
02460 n->setFixedType(Node::POS);
02461 }
02462
02463 #endif
02464
02465
02466
02467 if (closest_node->getNodeArray()->getObject()->getRigidHinge() == NULL) {
02468
02469 haptic_force = (closest_node->getF());
02470 }
02471 else {
02472
02473
02474
02475 Point3D tip_pt = getTip();
02476 float distance = closest_node->p_old.Dist(tip_pt);
02477 haptic_force = closest_node->p_old - tip_pt;
02478 haptic_force *= 10 * distance * distance;
02479 }
02480
02481
02482 grip_force = (sensor_activation - 0.5)*2 * 100;
02483 twist_force = 0;
02484
02485 if (debug)
02486 cerr << "haptic_force: " << haptic_force
02487 << ",twist=" << twist_force << ", grip=" << grip_force
02488 << endl;
02489 break;
02490 }
02491
02492 case deleting: {
02493 Object* other_obj = NULL;
02494
02495 #ifdef DELETE_CURRENT_OBJECT_ONLY
02496 other_obj = current_object;
02497 #else
02498
02499 closest_node = objectarray_p->FindClosestUnlinkedNode(getTip());
02500
02501
02502 if (closest_node) {
02503 other_obj = closest_node->getNodeArray()->getObject();
02504 }
02505 #endif
02506
02507
02508 if (sensor_p->active[0] && other_obj) {
02509 other_obj->CuttingByDeleting(this);
02510 }
02511 break;
02512 }
02513
02514 case coloring: {
02515 if (sensor_p->active[0] < 0.5) break;
02516
02517
02518 closest_node = objectarray_p->FindClosestUnlinkedNode(getTip());
02519 if (!closest_node) break;
02520
02521
02522 Object* other_obj = closest_node->getNodeArray()->getObject();
02523 cerr << "Coloring on object [" << other_obj->getName() << "]\n";
02524 int color = 10;
02525
02526
02527 Point3D min, max;
02528 getBoundingBox(&min, &max);
02529
02530
02531 other_obj->ColorNodesWithinBoundingBox(min, max, color);
02532
02533 break;
02534 }
02535
02536 case poking: {
02537
02538 break;
02539 }
02540
02541 case ablating:
02542 case cauterizing:
02543
02544
02545 #if defined(SOUND) && defined(SUN)
02546
02547 if (sensor_p->num_active > 1) {
02548 if (sensor_p->active[1] > 0.5) {
02549 system("/usr/bin/audioplay fastbusy.au &");
02550 }
02551 }
02552 #endif
02553 break;
02554
02555 case none:
02556
02557 break;
02558
02559 default:
02560
02561 break;
02562
02563 }
02564
02565
02566
02567 if (sensor_p->type == Sensor::haptic_v1_sensor) {
02568 Haptic_v1* haptic_p = (Haptic_v1*)sensor_p;
02569 haptic_p->force = haptic_force;
02570 if (haptic_p->GetGridMode() == false) {
02571 haptic_p->twist_force = twist_force;
02572 haptic_p->grip_force = grip_force;
02573 }
02574 else {
02575
02576 if (closest_node && (sensor_p->active[0] > 0.5)) {
02577 haptic_p->SetActive(true);
02578 }
02579 else {
02580 haptic_p->SetActive(false);
02581 }
02582 }
02583
02584
02585
02586 if (debug) {
02587 cerr << "[" << getName() << "]- haptic force = " << haptic_force
02588 << ", " << haptic_force.Length() << endl;
02589 }
02590 }
02591 }
02592
02593
02594
02595 void Object::HandleSpontaneousBehavior()
02596 {
02597
02598
02599
02600
02601
02602 switch (behavior) {
02603 case beating: {
02604 const double repeat_interval = 1.0;
02605 const double magnitude = 0.2;
02606 extern Timer global_timer;
02607 double t = global_timer.GetElapsedTime();
02608 t /= repeat_interval;
02609 t = t - int(t);
02610 t *= magnitude;
02611
02612
02613 nodearray.setToInitialPosition();
02614 nodearray.ScaleByNormal(t);
02615
02616 dl_needs_refresh = 1;
02617 addEverythingToUpdateList();
02618 break;
02619 }
02620
02621 case fluid: {
02622
02623 extern int iteration;
02624
02625 const int iterations_per_update = 5;
02626
02627
02628 float viscosity = getEdgeArray()->getEdge(0)->getSpringConstant();
02629
02630 PerlinNoise* noise = PerlinNoise::Instance();
02631 if ((iteration % iterations_per_update) == 0) {
02632 NodeArray* fluid_nodes = getNodeArray();
02633 int numnodes = fluid_nodes->getNumNodes();
02634 for (int i = 0; i < numnodes; i++) {
02635 Node* node = fluid_nodes->getNode(i);
02636 double y = noise->pnoise(node->p.x, node->p.z,
02637 ((float)iteration / iterations_per_update / viscosity));
02638 node->p.y = getHeight() + y / 10;
02639 }
02640
02641 addEverythingToUpdateList();
02642 dl_needs_refresh = 1;
02643 }
02644 break;
02645 }
02646
02647 default:
02648
02649 break;
02650
02651 }
02652 }
02653
02654
02655
02656 void Object::Draw()
02657 {
02658 if (visible) {
02659 DrawGeometry();
02660 }
02661 if (selected)
02662 DrawBoundingBox();
02663 }
02664
02665
02666 void Object::DrawGeometry()
02667 {
02668 if (debug) cerr << "Object[" << name << "]::Draw(" << &display_mode << ")\n";
02669
02670
02671 GLint rendermode;
02672 glGetIntegerv(GL_RENDER_MODE, &rendermode);
02673
02674
02675 extern int do_display_lists;
02676 if (do_display_lists && !dl_needs_refresh &&
02677 (display_mode == last_display_mode) && (rendermode == GL_RENDER)) {
02678 glCallList(dl_id);
02679 return;
02680 }
02681
02682
02683 if (dl_id == -1) {
02684
02685 dl_id = glGenLists(1);
02686
02687 }
02688 else {
02689
02690 glDeleteLists(dl_id, 1);
02691
02692
02693
02694 }
02695
02696
02697
02698
02699 if (do_display_lists) {
02700 glNewList(dl_id, GL_COMPILE_AND_EXECUTE);
02701
02702 }
02703 dl_needs_refresh = 0;
02704 last_display_mode = display_mode;
02705 if (debug) cerr << "Object[" << getName() << "- regen display-list\n";
02706
02707
02708
02709 Point3D mmin, mmax; getBoundingBox(&mmin, &mmax);
02710 nodearray.computeStats();
02711
02712
02713 if (rendermode == GL_SELECT)
02714 glPushName(objectarray_p->getIndex(this));
02715
02716
02717 {
02718 glDisable(GL_LIGHTING);
02719 glShadeModel(GL_FLAT);
02720
02721
02722 if (display_mode.draw_nodenormals)
02723 { nodearray.drawnormals(); }
02724
02725
02726 if (display_mode.draw_facenormals)
02727 { facearray.drawnormals(); }
02728
02729
02730
02731 if (display_mode.draw_tetranormals)
02732 { tetraarray.drawnormals(); }
02733
02734
02735 if ((type == faces_only) && display_mode.draw_wireover) {
02736 glColor3d(0,0, 0);
02737 edgearray.drawover(drawover_amount);
02738 }
02739
02740
02741 if ((type == tetras_only) && display_mode.draw_wireover) {
02742 glColor3d(0, 0, 0);
02743
02744 for (int i=0; i<facearray.getNumFaces(); i++) {
02745 Face* myface = facearray.getFace(i);
02746 if (myface->getTetraLink(1) == NULL) {
02747 for (int j=0; j<3; j++) {
02748 Edge* myedge = myface->getEdgeLink(j);
02749 if (myedge) myedge->drawover(drawover_amount);
02750 }
02751 }
02752 }
02753 }
02754
02755 if (display_mode.draw_initial)
02756 { edgearray.drawinitial(); nodearray.drawinitial(); }
02757
02758
02759 if (display_mode.draw_collisions)
02760 { facearray.drawmarkers(); }
02761
02762
02763 if (display_mode.draw_nodelabels)
02764 { glColor3d(0.5, 1.0, 1.0); nodearray.drawlabels(label_offset); }
02765
02766
02767 if (display_mode.draw_edgelabels)
02768 { glColor3d(1.0, 1.0, 0.5); edgearray.drawlabels(label_offset); }
02769
02770
02771 if (display_mode.draw_facelabels)
02772 { glColor3d(0.5, 1.0, 0.5); facearray.drawlabels(label_offset); }
02773
02774
02775 if (display_mode.draw_tetralabels)
02776 { glColor3d(0.0, 1.0, 1.0); tetraarray.drawlabels(label_offset); }
02777
02778
02779 if (display_mode.draw_objectlabels)
02780 { glColor3d(1.0, 0.0, 0.0); DrawLabel(); }
02781 }
02782
02783
02784 extern int do_textures;
02785 if (do_textures && texture && (type == faces_only) &&
02786 ((display_mode.mode == DisplayMode::flat) ||
02787 (display_mode.mode == DisplayMode::smooth))){
02788
02789 glEnable(GL_TEXTURE_2D);
02790
02791
02792 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
02793
02794
02795
02796 if (texture_mode == Object::texture_env_mode(0))
02797 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
02798 else if (texture_mode == texture_env_mode(1))
02799 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
02800 else if (texture_mode == Object::texture_env_mode(2))
02801 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
02802 else if (texture_mode == Object::texture_env_mode(3))
02803 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02804
02805 if (texture_wrap == Object::clamp) {
02806 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
02807 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
02808 }
02809 else {
02810 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
02811 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
02812 }
02813
02814 if (texture_filter == Object::linear) {
02815 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02816 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02817 }
02818 else {
02819 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02820 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02821 }
02822
02823
02824 if (debug)
02825 cerr << "applying " << texture_size.x << "x" << texture_size.y
02826 << " texture...\n";
02827
02828
02829
02830 int crop_w = 1,crop_h = 1;
02831 int grab_w = 256,grab_h = 256;
02832 if ((texture_size.x == 64) || (texture_size.x == 128) ||
02833 (texture_size.x == 256) || (texture_size.x == 512) || (texture_size.x == 1024))
02834 {
02835 grab_w = texture_size.x;
02836 crop_w = 0;
02837 }
02838 if ((texture_size.y == 64) || (texture_size.y == 128) ||
02839 (texture_size.y == 256) || (texture_size.y == 512) || (texture_size.y == 1024))
02840 {
02841 grab_h = texture_size.y;
02842 crop_h = 0;
02843 }
02844
02845 unsigned char* texture2 = NULL;
02846 int d = texture_size.z;
02847 if (crop_w*crop_h) {
02848 cerr << "cropping texture to be power of 2...\n";
02849 if (!texture2) {
02850 texture2 = (unsigned char*)malloc(grab_w*grab_h*d*sizeof(unsigned char));
02851 }
02852
02853 int texWidth = (grab_w > texture_size.x ? texture_size.x : grab_w);
02854 int texHeight = (grab_h > texture_size.y ? texture_size.y : grab_h);
02855
02856 for (int count = 0; count < texHeight; count++)
02857 memcpy((char *)texture2 + count*grab_w*d, (char *)texture + (count)*texture_size.x*d, texWidth*d);
02858 }
02859 else
02860 texture2 = (unsigned char*)texture;
02861
02862 switch (d) {
02863 case 1:
02864 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, grab_w,
02865 grab_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texture2);
02866 break;
02867 case 3:
02868 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, grab_w,
02869 grab_h, 0, GL_RGB, GL_UNSIGNED_BYTE, texture2);
02870 break;
02871 case 4:
02872 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, grab_w,
02873 grab_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture2);
02874 break;
02875 default:
02876 break;
02877 }
02878
02879
02880
02881
02882 }
02883
02884
02885 switch (type) {
02886 case nodes_only: {
02887 glDisable(GL_LIGHTING);
02888 nodearray.DrawNodes();
02889 break;
02890 }
02891 case edges_only: {
02892
02893
02894 if (do_textures && texture) {
02895 glEnable(GL_TEXTURE_2D);
02896 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
02897 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
02898 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
02899 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02900 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02901 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_size.x,
02902 texture_size.y,0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
02903
02904
02905
02906
02907
02908
02909
02910 glDisable(GL_LIGHTING);
02911 }
02912 else {
02913
02914 glEnable(GL_LIGHTING);
02915 glShadeModel(GL_FLAT);
02916 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
02917 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
02918 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
02919 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
02920
02921 glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
02922 glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
02923 glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
02924 glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
02925 }
02926 edgearray.DrawEdges();
02927 glDisable(GL_TEXTURE_2D);
02928 if (display_mode.mode == DisplayMode::wireframe)
02929 nodearray.DrawNodes();
02930 break;
02931 }
02932 case faces_only: {
02933
02934 facearray.computeNormals();
02935
02936
02937 nodearray.interpolateNormals();
02938
02939
02940 if (display_mode.mode == DisplayMode::wireframe) {
02941 glDisable(GL_LIGHTING);
02942 edgearray.DrawEdges();
02943 nodearray.DrawNodes();
02944 }
02945
02946
02947 if ((display_mode.mode == DisplayMode::flat) ||
02948 (display_mode.mode == DisplayMode::smooth)) {
02949
02950 glEnable(GL_LIGHTING);
02951
02952
02953 if (display_mode.mode == DisplayMode::flat) glShadeModel(GL_FLAT);
02954 else glShadeModel(GL_SMOOTH);
02955
02956 {
02957
02958 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
02959 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
02960 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
02961 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
02962
02963
02964 glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
02965 glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
02966 glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
02967 glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
02968 }
02969
02970
02971 facearray.DrawFaces(int(do_textures && texture));
02972 }
02973 break;
02974 }
02975 case tetras_only: {
02976 if (dynamics == deformable) {
02977
02978 facearray.computeNormals();
02979
02980
02981 nodearray.interpolateTetraNormals();
02982 }
02983
02984
02985 if (display_mode.mode == DisplayMode::wireframe) {
02986 glDisable(GL_LIGHTING);
02987 edgearray.DrawEdges();
02988 nodearray.DrawNodes();
02989 }
02990
02991
02992 if ((display_mode.mode == DisplayMode::flat) ||
02993 (display_mode.mode == DisplayMode::smooth)) {
02994
02995 glEnable(GL_LIGHTING);
02996
02997
02998 if (display_mode.mode == DisplayMode::flat) glShadeModel(GL_FLAT);
02999 else glShadeModel(GL_SMOOTH);
03000
03001 {
03002 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
03003 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
03004 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
03005 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
03006
03007 glColor4f(mat_ambient[0],mat_ambient[1],mat_ambient[2],mat_ambient[3]);
03008
03009 glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
03010 glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
03011 glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
03012 glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
03013 }
03014
03015
03016 tetraarray.DrawTetras(int(do_textures && texture));
03017 }
03018 break;
03019 }
03020 }
03021
03022
03023 glDisable(GL_TEXTURE_2D);
03024
03025 {
03026
03027
03028 if (display_mode.draw_tienodes) {
03029
03030 nodearray.drawtienodes();
03031
03032 }
03033
03034
03035 if (display_mode.draw_boundingspheres) {
03036
03037
03038
03039 extern springCore* springApp;
03040
03041 switch (springApp->getCollisionAlgorithm()) {
03042
03043
03044
03045
03046
03047 case springCore::BOUNDING_SPHERE_CD: {
03048
03049 if (boundingSphereRoot) {
03050 boundingSphereRoot->drawSubtree();
03051
03052 }
03053
03054 break;
03055
03056 }
03057
03058
03059
03060
03061
03062 case springCore::AABB_CD: {
03063
03064 if (boundingBoxRoot) {
03065
03066 boundingBoxRoot->draw();
03067
03068 }
03069
03070 break;
03071
03072 }
03073
03074 }
03075 }
03076
03077
03078
03079 if (display_mode.draw_principalaxis) {
03080 getNodeArray()->PrincipalAxes();
03081 DrawPrincipalAxes();
03082 }
03083 }
03084
03085
03086 if (rendermode == GL_SELECT)
03087 glPopName();
03088
03089
03090
03091 if (do_display_lists) {
03092 glEndList();
03093
03094 }
03095 }
03096
03097
03098 void Object::DrawBoundingBox()
03099 {
03100 Point3D min, max;
03101 getBoundingBox(&min, &max);
03102 glDisable(GL_LIGHTING);
03103 glColor3f(1.0, 0.0, 0.0);
03104
03105 glBegin(GL_LINE_LOOP);
03106 glVertex3d(min.x, min.y, min.z);
03107 glVertex3d(max.x, min.y, min.z);
03108 glVertex3d(max.x, max.y, min.z);
03109 glVertex3d(min.x, max.y, min.z);
03110 glEnd();
03111
03112 glBegin(GL_LINE_LOOP);
03113 glVertex3d(min.x, min.y, max.z);
03114 glVertex3d(max.x, min.y, max.z);
03115 glVertex3d(max.x, max.y, max.z);
03116 glVertex3d(min.x, max.y, max.z);
03117 glEnd();
03118
03119 glBegin(GL_LINES);
03120 glVertex3d(min.x, min.y, min.z);
03121 glVertex3d(min.x, min.y, max.z);
03122 glVertex3d(max.x, min.y, min.z);
03123 glVertex3d(max.x, min.y, max.z);
03124 glVertex3d(max.x, max.y, min.z);
03125 glVertex3d(max.x, max.y, max.z);
03126 glVertex3d(min.x, max.y, min.z);
03127 glVertex3d(min.x, max.y, max.z);
03128 glEnd();
03129 }
03130
03131 void Object::DrawLabel()
03132 {
03133
03134 extern RasterFont* font_p;
03135 Point3D center = getCenter();
03136 font_p->printString(getName(), center.x,center.y,center.z);
03137 }
03138
03139 void Object::DrawPrincipalAxes()
03140 {
03141
03142
03143
03144
03145 NodeArray *na = getNodeArray();
03146 Point3D bmin, bmax;
03147 getBoundingBox(&bmin, &bmax);
03148 double temp1 = MAX3(fabs(bmin.x), fabs(bmin.y), fabs(bmin.z));
03149 double temp2 = MAX3(fabs(bmax.x), fabs(bmax.y), fabs(bmax.z));
03150 double max = MAX(temp1, temp2);
03151 double xx, xy, xz, yx, yy, yz, zx, zy, zz;
03152
03153 double U[3][3];
03154 na->getUmatrix(U);
03155
03156
03157 xx=U[0][0];
03158 xy=U[1][0];
03159 xz=U[2][0];
03160 yx=U[0][1];
03161 yy=U[1][1];
03162 yz=U[2][1];
03163 zx=U[0][2];
03164 zy=U[1][2];
03165 zz=U[2][2];
03166
03167 glDisable(GL_LIGHTING);
03168 glBegin(GL_LINES);
03169 glColor3f(1.0, 0.0, 0.0);
03170 glVertex3d(-max*xx, -max*xy, -max*xz);
03171 glVertex3d(max*xx, max*xy, max*xz);
03172 glColor3f(1.0, 1.0, 0.0);
03173 glVertex3d(-max*yx, -max*yy, -max*yz);
03174 glVertex3d(max*yx, max*yy, max*yz);
03175 glColor3f(0.0, 1.0, 0.0);
03176 glVertex3d(-max*zx, -max*zy, -max*zz);
03177 glVertex3d(max*zx, max*zy, max*zz);
03178 glEnd();
03179 }
03180
03181 void Object::GeometryReplicate(GeometryReplicator* gr)
03182 {
03183 if (debug)
03184 cerr << "Object[" << getName() << "]::GeometryReplicate(" << gr << ")\n";
03185
03186
03187 if (!gr) return;
03188
03189
03190 if (!dl_needs_refresh) return;
03191
03192
03193
03194 if (being_modified) return;
03195
03196
03197 const int buf_size = 1024;
03198 char buffer[buf_size];
03199 Timer timer;
03200
03201 {
03202 int s = sprintf(buffer, "%c%c%s", GR_CODE, GR_OBJECT, getName());
03203 gr->SendMessage(buffer, s);
03204 }
03205
03206 {
03207
03208 unsigned char* ubuffer = (unsigned char*)buffer;
03209 int n = 0;
03210 ubuffer[n++] = GR_CODE; ubuffer[n++] = GR_OBJ_ATTR;
03211 ubuffer[n++] = isVisible();
03212 { for (int i=0; i<4; i++) ubuffer[n++] = int(mat_ambient[i] * 255); }
03213 { for (int i=0; i<4; i++) ubuffer[n++] = int(mat_diffuse[i] * 255); }
03214 { for (int i=0; i<4; i++) ubuffer[n++] = int(mat_specular[i] * 255); }
03215 { for (int i=0; i<4; i++) ubuffer[n++] = int(mat_ambient[i] * 255); }
03216 ubuffer[n++] = int(mat_shininess[0] * 255);
03217
03218
03219
03220
03221 gr->SendMessage((char*)ubuffer, n);
03222 }
03223
03224
03225
03226 if (debug) {
03227 cerr << "\ttime to send attributes = " << timer.GetElapsedTime() << endl;
03228 timer.Reset();
03229 }
03230 if (texture) {
03231 unsigned char* ubuffer = (unsigned char*)buffer;
03232 int n = 0;
03233
03234 ubuffer[n++] = GR_CODE; ubuffer[n++] = GR_TEXTURE;
03235 ubuffer[n++] = texture_size.x / 255; ubuffer[n++] = texture_size.x % 255;
03236 ubuffer[n++] = texture_size.y / 255; ubuffer[n++] = texture_size.y % 255;
03237 ubuffer[n++] = texture_size.z / 255; ubuffer[n++] = texture_size.z % 255;
03238
03239
03240 int size = texture_size.x * texture_size.y * texture_size.z;
03241 memcpy(&(buffer[n]), texture, size);
03242 gr->SendMessage(buffer, n+size);
03243 }
03244 if (debug) {
03245 cerr << "\ttime to send texture = " << timer.GetElapsedTime() << endl;
03246 timer.Reset();
03247 }
03248
03249
03250 nodearray.GeometryReplicate(gr);
03251 if (debug) {
03252 cerr << "\ttime to send nodes = " << timer.GetElapsedTime() << endl;
03253 timer.Reset();
03254 }
03255
03256
03257
03258 nodearray.CacheIndices();
03259
03260
03261 facearray.GeometryReplicate(gr);
03262 if (debug) {
03263 cerr << "\ttime to send faces = " << timer.GetElapsedTime() << endl;
03264 timer.Reset();
03265 }
03266 }
03267
03268
03269
03270 int Object::intersectsBoundingSphere(Object* test_obj)
03271 {
03272 Point3D our_center = getCenter();
03273 Point3D test_obj_center = test_obj->getCenter();
03274 double dist_between_centers = our_center.Dist(test_obj_center);
03275 double dist_between_bspheres = getRadius() + test_obj->getRadius();
03276 int retval = ( (dist_between_centers < dist_between_bspheres) );
03277
03278 if (debug && retval)
03279 cerr << "[" << getName() << "] is inside bsphere of object ["
03280 << test_obj->getName() << "] dist = "
03281 << dist_between_centers << ", radii = "
03282 << getRadius() << " + " << test_obj->getRadius()
03283 << "=" << dist_between_bspheres << endl;
03284
03285 return(retval);
03286 }
03287
03288
03289
03290 int Object::intersectsBoundingBox(Object *obj, double e)
03291 {
03292 Point3D thismin, thismax;
03293 Point3D objmin, objmax;
03294 this->getBoundingBox(&thismin, &thismax);
03295 obj->getBoundingBox(&objmin, &objmax);
03296 if (e > 0.0) {
03297 Point3D p(e, e, e);
03298 thismin -= p;
03299 thismax += p;
03300 objmin -= p;
03301 objmax += p;
03302 }
03303 if (((thismax.x < objmin.x) || (thismin.x > objmax.x)) ||
03304 ((thismax.y < objmin.y) || (thismin.y > objmax.y)) ||
03305 ((thismax.z < objmin.z) || (thismin.z > objmax.z)))
03306 return(0);
03307 else
03308 return(1);
03309 }
03310
03311 Node* Object::findClosestNode(Point3D pt)
03312 {
03313 if (debug) cerr << "Object[" << name << "]::findClosestNode(" << pt << ")\n";
03314
03315 if (nodearray.getNumNodes() == 0)
03316 return(NULL);
03317
03318
03319
03320 #ifdef USE_SBBS
03321 int closest_node_index = nodearray.findCollisionNode(pt);
03322 #else
03323 int closest_node_index = nodearray.findClosestNode(pt);
03324 #endif
03325 if (closest_node_index < 0) return(NULL);
03326
03327
03328 return( nodearray.getNode(closest_node_index) );
03329 }
03330
03331
03332
03333
03334 double Object::findClosestNodesBetweenObjects(Object* other_obj,
03335 Node** our_node_p, Node** other_node_p)
03336 {
03337 if (debug)
03338 cerr << "Object[" << name << "]::findClosestNodesBetweenObjects("
03339 << other_obj << "," << our_node_p << "," << other_node_p << ")\n";
03340
03341
03342 double dist = nodearray.findClosestNodesBetweenNodeArrays(
03343 other_obj->getNodeArray(), our_node_p, other_node_p);
03344
03345
03346 return( dist );
03347 }
03348
03349
03350 void Object::CreateTestLine(int num_segs, double length, Point3D offset,
03351 int fix_end)
03352 {
03353 type = edges_only;
03354 dynamics = deformable;
03355 behavior = none;
03356 uses_viagra = 0;
03357 set_default_material_properties();
03358 nodearray.reset();
03359 edgearray.reset();
03360 facearray.reset();
03361 nodearray.allocateNodes(num_segs + 1);
03362 edgearray.allocateEdges(num_segs);
03363
03364 double seg_length = length/num_segs;
03365 for (int i = 0; i < (num_segs + 1); i++) {
03366 Point3D pt(offset.x + (double)i*seg_length, offset.y, offset.z);
03367 nodearray.addNode(pt);
03368 if (i != 0)
03369 edgearray.addEdge(i, i-1);
03370 }
03371 if (fix_end)
03372 nodearray.getNode(num_segs)->setFixedType(Node::POS);
03373
03374 nodearray.computeStats();
03375 }
03376
03377
03378 void Object::CreateNodeCloud(int num_nodes, int radius, Point3D offset)
03379 {
03380 type = nodes_only;
03381 dynamics = deformable;
03382 behavior = none;
03383 uses_viagra = 0;
03384 set_default_material_properties();
03385 nodearray.reset();
03386 edgearray.reset();
03387 facearray.reset();
03388 nodearray.allocateNodes(num_nodes);
03389
03390 for (int i = 0; i < num_nodes; i++) {
03391 Point3D pt(rand() % radius, rand() % radius, rand() % radius);
03392 pt += offset;
03393 nodearray.addNode(pt);
03394 }
03395
03396 nodearray.computeStats();
03397 }
03398
03399
03400 void Object::CreateEquiMesh(int numlevels, double edgelength)
03401 {
03402
03403 type = faces_only;
03404 dynamics = deformable;
03405 behavior = none;
03406 uses_viagra = 0;
03407 set_default_material_properties();
03408
03409 if (numlevels < 1) numlevels = 1;
03410
03411 int projected_num_nodes = (numlevels + 1)*(numlevels + 2)/2;
03412 nodearray.reset();
03413 edgearray.reset();
03414 facearray.reset();
03415 projected_num_nodes *= 2;
03416 nodearray.allocateNodes(projected_num_nodes);
03417 edgearray.allocateEdges(projected_num_nodes * 3);
03418 facearray.allocateFaces(projected_num_nodes * 2);
03419
03420 double cos30 = cos(PI/6.0);
03421 int node_index = 0;
03422 for (int i = 0; i <= numlevels; i++) {
03423 for (int j = 0; j <= i; j++) {
03424
03425 Point3D pt(i*edgelength*cos30, i*edgelength*0.5 - j*edgelength, 0.0);
03426 nodearray.addNode(pt);
03427
03428 if (i == numlevels)
03429 nodearray.getNode(node_index)->setFixedType(Node::POS);
03430
03431 if (i > 0) {
03432 if (j > 0 && j < i) {
03433 facearray.addFace(node_index, node_index - i - 1, node_index - 1);
03434 facearray.addFace(node_index, node_index - i, node_index - i - 1);
03435 }
03436 else if (j == i) {
03437 facearray.addFace(node_index, node_index - i - 1, node_index - 1);
03438 }
03439 }
03440 node_index++;
03441 }
03442 }
03443 }
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459 void Object::CreateTube(char orientation, int num_radii, int num_rings, double radius,
03460 double length, Point3D offset, int diag1, int diag2,
03461 int fix_num, double inner_radius,
03462 int cross1, int cross2, int capped,
03463 double sc1, double sc2, double rl_out,
03464 double rl_in, double rl_betw)
03465 {
03466 if (debug) cerr << "Object[" << name << "]::CreateTube(" << num_radii
03467 << ", " << radius << ", " << inner_radius << ", "
03468 << length << ", " << offset << ")\n";
03469
03470
03471 type = faces_only;
03472 dynamics = deformable;
03473 behavior = none;
03474 uses_viagra = 0;
03475 set_default_material_properties();
03476
03477
03478 int projected_num_nodes = num_rings * num_radii * 2;
03479 nodearray.reset();
03480 edgearray.reset();
03481 facearray.reset();
03482 projected_num_nodes *= 2;
03483 nodearray.allocateNodes(projected_num_nodes);
03484 edgearray.allocateEdges(projected_num_nodes * 6);
03485 facearray.allocateFaces(projected_num_nodes * 2);
03486
03487 int node_index = 0;
03488
03489
03490 int xdivide = ((num_rings == 1) ? 1 : (num_rings - 1));
03491
03492 {
03493 for (int ring = 0; ring < num_rings; ring++) {
03494 for (int spoke = 0; spoke < num_radii; spoke++) {
03495
03496 double angle = spoke * 2*PI/num_radii;
03497 Point3D pt;
03498
03499
03500 switch (orientation) {
03501 default:
03502 case 'x' : pt = Point3D(ring*length/(xdivide),
03503 radius*cos(angle),-radius*sin(angle));
03504 break;
03505 case 'y' : pt = Point3D(radius*cos(angle),
03506 ring*length/(xdivide),-radius*sin(angle));
03507 break;
03508 case 'z' : pt = Point3D(radius*cos(angle),
03509 -radius*sin(angle),ring*length/(xdivide));
03510 break;
03511 }
03512
03513
03514 pt += offset;
03515 nodearray.addNode(pt);
03516
03517
03518
03519
03520
03521 if (spoke != 0)
03522 edgearray.addEdge(node_index, (node_index - 1), rl_out, sc1);
03523 if (spoke == (num_radii - 1))
03524 edgearray.addEdge(node_index, (node_index - num_radii + 1), rl_out, sc1);
03525
03526
03527 if (ring != 0)
03528 edgearray.addEdge(node_index, (node_index - num_radii), rl_out, sc2);
03529
03530
03531 if (diag1 && ring != 0) {
03532 if (spoke != 0)
03533 edgearray.addEdge(node_index,(node_index - num_radii - 1),rl_out,sc2);
03534 else
03535 edgearray.addEdge(node_index, (node_index - 1), rl_out, sc2);
03536 }
03537
03538
03539 if (diag2 && ring != 0) {
03540 if (spoke != (num_radii - 1))
03541 edgearray.addEdge(node_index,(node_index - num_radii + 1),rl_out,sc2);
03542 else
03543 edgearray.addEdge(node_index,(node_index -2*num_radii + 1),rl_out,sc2);
03544 }
03545
03546
03547 if (diag1 && ring != 0) {
03548 int other = node_index - num_radii;
03549 if (spoke != 0) {
03550 facearray.addFace(node_index, other, (other - 1));
03551 facearray.addFace(node_index, (other - 1), (node_index - 1));
03552 }
03553 if (spoke == 0)
03554 facearray.addFace(node_index, other, (node_index - 1));
03555 if (spoke == (num_radii - 1))
03556 facearray.addFace(node_index, (other + 1), other);
03557 }
03558
03559
03560 if ((((num_rings - ring) <= fix_num) && (offset.x > 0)) ||
03561 ((ring < fix_num) && (offset.x < 0))) {
03562 nodearray.getNode(node_index)->setFixedType(Node::POS);
03563 }
03564
03565 node_index++;
03566 }
03567 }
03568 }
03569
03570
03571 if (inner_radius > 0.0) {
03572 int outer_num = node_index;
03573 radius = inner_radius;
03574
03575 for (int ring = 0; ring < num_rings; ring++) {
03576 for (int spoke = 0; spoke < num_radii; spoke++) {
03577
03578 double angle = spoke * 2*PI/num_radii;
03579 Point3D pt;
03580
03581
03582 switch (orientation) {
03583 default:
03584 case 'x' : pt = Point3D(ring*length/(xdivide),
03585 radius*cos(angle),-radius*sin(angle));
03586 break;
03587 case 'y' : pt = Point3D(radius*cos(angle),
03588 ring*length/(xdivide),-radius*sin(angle));
03589 break;
03590 case 'z' : pt = Point3D(radius*cos(angle),
03591 -radius*sin(angle),ring*length/(xdivide));
03592 break;
03593 }
03594
03595
03596 pt += offset;
03597 nodearray.addNode(pt);
03598
03599
03600
03601
03602
03603 if (spoke != 0)
03604 edgearray.addEdge(node_index, (node_index - 1), rl_in, sc1);
03605 if (spoke == (num_radii - 1))
03606 edgearray.addEdge(node_index, (node_index - num_radii + 1), rl_in, sc1);
03607
03608
03609 if (ring != 0)
03610 edgearray.addEdge(node_index, (node_index - num_radii), rl_in, sc2);
03611
03612
03613 if (diag1 && ring != 0) {
03614 if (spoke != 0)
03615 edgearray.addEdge(node_index,(node_index - num_radii - 1),rl_in,sc2);
03616 else
03617 edgearray.addEdge(node_index, (node_index - 1), rl_in, sc2);
03618 }
03619
03620
03621 if (diag2 && ring != 0) {
03622 if (spoke != (num_radii - 1))
03623 edgearray.addEdge(node_index,(node_index - num_radii + 1),rl_in,sc2);
03624 else
03625 edgearray.addEdge(node_index,(node_index -2*num_radii + 1),rl_in,sc2);
03626 }
03627
03628
03629 edgearray.addEdge(node_index, node_index - outer_num, rl_betw, sc1);
03630
03631
03632
03633 if (cross1) {
03634 int other = node_index - outer_num;
03635 if (ring != (num_rings - 1))
03636 edgearray.addEdge(node_index, (other + num_radii), rl_betw, sc2);
03637 if (ring != 0)
03638 edgearray.addEdge(node_index, (other - num_radii), rl_betw, sc2);
03639 }
03640
03641
03642 if (cross2) {
03643 int other = node_index - outer_num;
03644 if (spoke != 0)
03645 edgearray.addEdge(node_index, (other - 1), rl_betw, sc1);
03646 else
03647 edgearray.addEdge(node_index, (other + num_radii - 1), rl_betw, sc1);
03648 if (spoke != (num_radii - 1))
03649 edgearray.addEdge(node_index, (other + 1), rl_betw, sc1);
03650 else
03651 edgearray.addEdge(node_index, (other - num_radii + 1), rl_betw, sc1);
03652 }
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670 if (capped) {
03671 int other = node_index - outer_num;
03672 if (ring == 0) {
03673 if (spoke != 0) {
03674 facearray.addFace(node_index, (node_index - 1), (other - 1));
03675 facearray.addFace(node_index, (other - 1), other);
03676 }
03677 if (spoke == 0)
03678 facearray.addFace(node_index, (other + num_radii - 1), other);
03679 if (spoke == (num_radii - 1))
03680 facearray.addFace(node_index, other,(node_index - num_radii +1));
03681 }
03682 if (ring == (num_rings -1)) {
03683 if (spoke != 0) {
03684 facearray.addFace(node_index, (other - 1), (node_index - 1));
03685 facearray.addFace(node_index, other, (other - 1));
03686 }
03687 if (spoke == 0)
03688 facearray.addFace(node_index, other, (other + num_radii - 1));
03689 if (spoke == (num_radii - 1))
03690 facearray.addFace(node_index,(node_index - num_radii +1),other);
03691 }
03692 }
03693
03694
03695 if ((((num_rings - ring) <= fix_num) && (offset.x > 0)) ||
03696 ((ring < fix_num) && (offset.x < 0))) {
03697 nodearray.getNode(node_index)->setFixedType(Node::POS);
03698 }
03699
03700 node_index++;
03701 }
03702 }
03703 }
03704
03705
03706
03707 if (inner_radius == 0.0 && capped) {
03708 int outer_num = node_index;
03709 Point3D center0 = offset;
03710 Point3D center1 = offset + (nodearray.getNode(outer_num - num_radii)->p -
03711 nodearray.getNode(0)->p);
03712
03713 int i;
03714 nodearray.addNode(center0);
03715 for (i = 0; i < num_radii; i++) {
03716 facearray.addFace(node_index, i, (i+1)%num_radii);
03717 }
03718 node_index++;
03719
03720 if (num_rings > 1) {
03721 nodearray.addNode(center1);
03722 for (i = 0; i < num_radii; i++) {
03723 facearray.addFace(node_index, (i+1)%num_radii + outer_num - num_radii,
03724 i + outer_num - num_radii);
03725 }
03726 node_index++;
03727 }
03728 }
03729
03730
03731 nodearray.computeStats();
03732
03733
03734 facearray.computeNormals();
03735
03736
03737 nodearray.interpolateNormals();
03738 }
03739
03740
03741 int Object::CreateSphere(int numlayers, double radius, double inner)
03742 {
03743
03744 type = faces_only;
03745 dynamics = deformable;
03746 behavior = none;
03747 uses_viagra = 0;
03748 set_default_material_properties();
03749
03750 if (numlayers < 2) numlayers = 2;
03751
03752 int projected_num_nodes = 2000;
03753 nodearray.reset();
03754 edgearray.reset();
03755 facearray.reset();
03756 nodearray.allocateNodes(projected_num_nodes);
03757 edgearray.allocateEdges(projected_num_nodes * 3);
03758 facearray.allocateFaces(projected_num_nodes * 2);
03759
03760 Point3D pt;
03761 int shells = 1;
03762 int top = 0;
03763 int outer = 0;
03764 if (inner > 0.0)
03765 shells = 2;
03766 for (int k = 0; k < shells; k++) {
03767 if (k == 1)
03768 radius = inner;
03769
03770
03771
03772 {
03773 for (int layer = 0; layer < numlayers; layer++) {
03774 if (layer == 0) {
03775 pt = Point3D(0, radius, 0);
03776 nodearray.addNode(pt);
03777 }
03778 else {
03779 double h = radius*sin((PI/2)*(numlayers-1-layer)/(numlayers-1));
03780 double r = sqrt(radius*radius - h*h);
03781 int n = 5*(int)(pow((double) 2, (layer-1)));
03782 for (int i = 0; i < n; i++) {
03783 double angle = i*2*PI/n;
03784 pt = Point3D(r*sin(angle), h, r*cos(angle));
03785 nodearray.addNode(pt);
03786 }
03787 }
03788 }
03789 }
03790
03791 if (k == 0)
03792 top = nodearray.getNumNodes();
03793
03794 {
03795 for (int layer = 0; layer < (numlayers - 1); layer ++) {
03796 if (layer == 0) {
03797 pt = Point3D(0, -radius, 0);
03798 nodearray.addNode(pt);
03799 nodearray.getNode(top)->setFixedType(Node::POS);
03800 }
03801 else {
03802 double h = radius*sin((PI/2)*(numlayers-1-layer)/(numlayers-1));
03803 double r = sqrt(radius*radius - h*h);
03804 int n = 5*(int)(pow((double) 2, (layer-1)));
03805 for (int i = 0; i < n; i++) {
03806 double angle = i*2*PI/n;
03807 pt = Point3D(r*sin(angle), -h, r*cos(angle));
03808 nodearray.addNode(pt);
03809 }
03810 }
03811 }
03812 }
03813
03814
03815 if (k == 1) {
03816 for (int m = 0; m < outer; m++)
03817 edgearray.addEdge(m, outer+m);
03818 }
03819
03820
03821 for (int i = 0; i < 5; i++) {
03822 if (numlayers > 2) {
03823 facearray.addFace(outer,outer+i+1, outer+(i+1)%5 + 1);
03824 facearray.addFace(outer+top, outer+(i+1)%5 +1+top, outer+i+1 +top);
03825 }
03826 else {
03827 facearray.addFace(outer, outer+i+1, outer+(i+1)%5 + 1);
03828 facearray.addFace(outer+top, outer+(i+1)%5 + 1, outer+i+1);
03829 }
03830 }
03831 int min = outer; int min2;
03832 int max = outer; int max2;
03833 int fl;
03834 for (int layer = 1; layer < (numlayers - 1); layer++) {
03835 min = max + 1;
03836 max = max + 5*(int)(pow((double) 2,(layer-1)));
03837 min2 = max + 1;
03838 max2 = max + 5*(int)(pow((double) 2,layer));
03839 if (layer == (numlayers-2))
03840 fl = 0;
03841 else
03842 fl = top;
03843 int n = 5*(int)(pow((double) 2, (layer-1)));
03844 for (int i = 0; i < n; i++) {
03845
03846 facearray.addFace(min + i, min2 + 2*i, min2 + 2*i +1);
03847 if (i == (n - 1))
03848 facearray.addFace(min + i, min2 + 2*i + 1, min);
03849 else
03850 facearray.addFace(min + i, min2 + 2*i + 1, min +i+1);
03851 if (i == 0)
03852 facearray.addFace(min + i, max2, min2 + 2*i);
03853 else
03854 facearray.addFace(min + i, min2 + 2*i - 1, min2 + 2*i);
03855
03856 facearray.addFace(min +i+top, min2 + 2*i +1+fl, min2 + 2*i +fl);
03857 if (i == (n - 1))
03858 facearray.addFace(min +i+top, min+top, min2 + 2*i + 1+fl);
03859 else
03860 facearray.addFace(min +i+top, min +i+1+top, min2 + 2*i + 1+fl);
03861 if (i == 0)
03862 facearray.addFace(min +i+top, min2 + 2*i +fl, max2 +fl);
03863 else
03864 facearray.addFace(min +i+top, min2 + 2*i +fl, min2 + 2*i -1+fl);
03865 }
03866 }
03867 outer = nodearray.getNumNodes(); printf("%d %d\n", top, outer);
03868 }
03869
03870 nodearray.computeStats();
03871
03872
03873 facearray.computeNormals();
03874
03875
03876 nodearray.interpolateNormals();
03877 return (top);
03878 }
03879
03880
03881
03882 void Object::CreateThread(double length, double node_spacing, int orientation,
03883 Point3D offset, double edgethresh_in, int first_seg)
03884 {
03885 if (debug) cerr << "Object[" << name << "]::CreateThread(" << length <<
03886 ", " << node_spacing << ", " << offset << ")\n";
03887
03888
03889 type = edges_only;
03890
03891 edgethresh = edgethresh_in;
03892 dynamics = articulate;
03893
03894 nummethod = quasi;
03895 behavior = none;
03896 uses_viagra = 0;
03897 set_default_material_properties();
03898
03899
03900
03901
03902 int num_nodes = (int)(length/node_spacing) + 1;
03903
03904
03905 nodearray.reset();
03906 edgearray.reset();
03907 facearray.reset();
03908 nodearray.allocateNodes(2*num_nodes);
03909 edgearray.allocateEdges(2*num_nodes);
03910 facearray.allocateFaces(10);
03911
03912
03913 int last_node_index = -1;
03914 for (int i=0; i < num_nodes; i++) {
03915 Point3D pt = offset;
03916 switch (orientation) {
03917 case 0: pt.x += i*node_spacing; break;
03918 case 1: pt.y += i*node_spacing; break;
03919 case 2: pt.z += i*node_spacing; break;
03920 }
03921 int node_index = nodearray.addNode(pt);
03922
03923
03924
03925 if (last_node_index == -1)
03926 last_node_index = node_index;
03927 else {
03928
03929 int edge_index =
03930 edgearray.addEdge(last_node_index, node_index, -1, 20, 40);
03931 edgearray.getEdge(edge_index)->setSpringConstant(2.0);
03932
03933
03934 last_node_index = node_index;
03935 }
03936 if (i == 0)
03937 i += first_seg;
03938
03939
03940 }
03941
03942
03943 nodearray.computeStats();
03944
03945
03946 facearray.computeNormals();
03947
03948
03949 nodearray.interpolateNormals();
03950 }
03951
03952
03953 void Object::CreateEdgeRing(Point3D center, double radius, int numedges,
03954 double edgethresh_in)
03955 {
03956 if (debug) cerr << "Object[" << name << "]::CreateEdgeRing(" << center <<
03957 ", " << radius << ", " << numedges << ")\n";
03958
03959
03960 type = edges_only;
03961
03962 edgethresh = edgethresh_in;
03963 dynamics = rigid;
03964 nummethod = quasi;
03965 behavior = none;
03966 uses_viagra = 0;
03967 set_default_material_properties();
03968
03969 int num_nodes = numedges;
03970
03971
03972 nodearray.reset();
03973