static void rib_camera(FILE *o, Lib3dsFile *f, Lib3dsMatrix M) { Lib3dsNode *c; Lib3dsNode *t; const char *name=camera; ASSERT(f); if (!name) { if (f->cameras) { name=f->cameras->name; } } if (!name) { fprintf(stderr, "***ERROR*** No camera found!\n"); return; } c=lib3ds_file_node_by_name(f, name, LIB3DS_CAMERA_NODE); t=lib3ds_file_node_by_name(f, name, LIB3DS_TARGET_NODE); if (!c || !t) { fprintf(stderr, "***ERROR*** Invalid camera/target!\n"); return; } lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll); rib_concat_transform(o, M); fprintf(o, "Camera \"perspective\" \"float fov\" [%f]\n", c->data.camera.fov); }
static void rib_lights(FILE *o, Lib3dsFile *f, Lib3dsMatrix M) { Lib3dsLight *light; Lib3dsNode *l; Lib3dsNode *s; int i=1; for (light=f->lights; light; light=light->next) { l=lib3ds_file_node_by_name(f, light->name, LIB3DS_LIGHT_NODE); s=lib3ds_file_node_by_name(f, light->name, LIB3DS_SPOT_NODE); if (!l) { fprintf(stderr, "***ERROR*** Invalid light!\n"); exit(1); } if (s) { Lib3dsVector pos,spot; lib3ds_vector_copy(pos, l->data.light.pos); lib3ds_vector_copy(spot, s->data.spot.pos); fprintf(o, "LightSource " "\"lib3dslight\" " "%d " "\"string lighttype\" [\"spot\"] " "\"point from\" [%f %f %f] " "\"point to\" [%f %f %f]\n", i, pos[0], pos[1], pos[2], spot[0], spot[1], spot[2] ); } else { Lib3dsVector pos; lib3ds_vector_copy(pos, l->data.light.pos); fprintf(o, "LightSource " "\"pointlight\" " "%d " "\"from\" [%f %f %f]\n", i, pos[0], pos[1], pos[2] ); } fprintf(o, "Illuminate %d 1\n", i); ++i; } }
/*! * */ static void display(void) { Lib3dsNode *c,*t; Lib3dsMatrix M; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (!file) { return; } c=lib3ds_file_node_by_name(file, camera, LIB3DS_CAMERA_NODE); t=lib3ds_file_node_by_name(file, camera, LIB3DS_TARGET_NODE); if (!c || !t) { return; } glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( c->data.camera.fov, 1.0*gl_width/gl_height, 100.0, 20000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(-90, 1.0,0,0); { GLfloat lightPos[] = {0.0f, -1.0f, 0.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, lightPos); glPushMatrix(); glTranslatef(0,-10,0); glutSolidTeapot(10.0); glPopMatrix(); } lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll); glMultMatrixf(&M[0][0]); { Lib3dsNode *p; for (p=file->nodes; p!=0; p=p->next) { render_node(p); } } if (!halt) { current_frame+=1.0; if (current_frame>file->frames) { current_frame=0; } lib3ds_file_eval(file, current_frame); glutSwapBuffers(); glutPostRedisplay(); } }
static void light_update(Lib3dsLight *l) { Lib3dsNode *ln, *sn; ln = lib3ds_file_node_by_name(file, l->name, LIB3DS_LIGHT_NODE); sn = lib3ds_file_node_by_name(file, l->name, LIB3DS_SPOT_NODE); if( ln != NULL ) { memcpy(l->color, ln->data.light.col, sizeof(Lib3dsRgb)); memcpy(l->position, ln->data.light.pos, sizeof(Lib3dsVector)); } if( sn != NULL ) memcpy(l->spot, sn->data.spot.pos, sizeof(Lib3dsVector)); }
static void construct_hierarchy(Lib3dsFile *file, Scene *scene) { std::list<Object*> *list = scene->get_object_list(); std::list<Object*>::iterator iter = list->begin(); while(iter != list->end()) { Object *obj = *iter; Lib3dsNode *n = lib3ds_file_node_by_name(file, obj->name.c_str(), LIB3DS_OBJECT_NODE); if(!n) { iter++; continue; } // get parent if(n->parent) { obj->parent = scene->get_node(n->parent->name); } // get children Lib3dsNode *child = n->childs; while(child) { XFormNode *child_node = scene->get_node(child->name); if(child_node) { (*iter)->children.push_back(child_node); } child = child->next; } iter++; } }
static void light_update(Lib3dsLight *l) { Lib3dsNode *ln, *sn; ln = lib3ds_file_node_by_name(file, l->name, LIB3DS_NODE_SPOTLIGHT); sn = lib3ds_file_node_by_name(file, l->name, LIB3DS_NODE_SPOTLIGHT_TARGET); if (ln != NULL) { Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)ln; memcpy(l->color, n->color, 3 * sizeof(float)); memcpy(l->position, n->pos, 3 * sizeof(float)); } if (sn != NULL) { Lib3dsTargetNode *n = (Lib3dsTargetNode*)sn; memcpy(l->target, n->pos, 3* sizeof(float)); } }
/*! * \ingroup node */ Lib3dsBool lib3ds_node_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io) { Lib3dsChunk c; switch (node->type) { case LIB3DS_AMBIENT_NODE: c.chunk=LIB3DS_AMBIENT_NODE_TAG; break; case LIB3DS_OBJECT_NODE: c.chunk=LIB3DS_OBJECT_NODE_TAG; break; case LIB3DS_CAMERA_NODE: c.chunk=LIB3DS_CAMERA_NODE_TAG; break; case LIB3DS_TARGET_NODE: c.chunk=LIB3DS_TARGET_NODE_TAG; break; case LIB3DS_LIGHT_NODE: if (lib3ds_file_node_by_name(file, node->name, LIB3DS_SPOT_NODE)) { c.chunk=LIB3DS_SPOTLIGHT_NODE_TAG; } else { c.chunk=LIB3DS_LIGHT_NODE_TAG; } break; case LIB3DS_SPOT_NODE: c.chunk=LIB3DS_L_TARGET_NODE_TAG; break; default: return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } { /*---- LIB3DS_NODE_ID ----*/ Lib3dsChunk c; c.chunk=LIB3DS_NODE_ID; c.size=8; lib3ds_chunk_write(&c,io); lib3ds_io_write_intw(io, node->node_id); } { /*---- LIB3DS_NODE_HDR ----*/ Lib3dsChunk c; c.chunk=LIB3DS_NODE_HDR; c.size=6+ 1+(Lib3dsDword)strlen(node->name) +2+2+2; lib3ds_chunk_write(&c,io); lib3ds_io_write_string(io, node->name); lib3ds_io_write_word(io, node->flags1); lib3ds_io_write_word(io, node->flags2); lib3ds_io_write_word(io, node->parent_id); } switch (c.chunk) { case LIB3DS_AMBIENT_NODE_TAG: { /*---- LIB3DS_COL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_COL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.ambient.col_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_OBJECT_NODE_TAG: { /*---- LIB3DS_PIVOT ----*/ Lib3dsChunk c; c.chunk=LIB3DS_PIVOT; c.size=18; lib3ds_chunk_write(&c,io); lib3ds_io_write_vector(io, node->data.object.pivot); } { /*---- LIB3DS_INSTANCE_NAME ----*/ Lib3dsChunk c; const char *name; if (strlen(node->data.object.instance)) { name=node->data.object.instance; c.chunk=LIB3DS_INSTANCE_NAME; c.size=6+1+(Lib3dsDword)strlen(name); lib3ds_chunk_write(&c,io); lib3ds_io_write_string(io, name); } } { int i; for (i=0; i<3; ++i) { if ((fabs(node->data.object.bbox_min[i])>LIB3DS_EPSILON) || (fabs(node->data.object.bbox_max[i])>LIB3DS_EPSILON)) { break; } } if (i<3) { /*---- LIB3DS_BOUNDBOX ----*/ Lib3dsChunk c; c.chunk=LIB3DS_BOUNDBOX; c.size=30; lib3ds_chunk_write(&c,io); lib3ds_io_write_vector(io, node->data.object.bbox_min); lib3ds_io_write_vector(io, node->data.object.bbox_max); } } { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.object.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_ROT_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_ROT_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_quat_track_write(&node->data.object.rot_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_SCL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_SCL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.object.scl_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } if (node->data.object.hide_track.keyL) { /*---- LIB3DS_HIDE_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_HIDE_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_bool_track_write(&node->data.object.hide_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } if (fabs(node->data.object.morph_smooth)>LIB3DS_EPSILON){ /*---- LIB3DS_MORPH_SMOOTH ----*/ Lib3dsChunk c; c.chunk=LIB3DS_MORPH_SMOOTH; c.size=10; lib3ds_chunk_write(&c,io); lib3ds_io_write_float(io, node->data.object.morph_smooth); } break; case LIB3DS_CAMERA_NODE_TAG: { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.camera.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_FOV_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_FOV_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin1_track_write(&node->data.camera.fov_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_ROLL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_ROLL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin1_track_write(&node->data.camera.roll_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_TARGET_NODE_TAG: { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.target.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_LIGHT_NODE_TAG: { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_COL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_COL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_SPOTLIGHT_NODE_TAG: { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.light.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_COL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_COL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.light.col_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_HOT_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_HOT_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin1_track_write(&node->data.light.hotspot_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_FALL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_FALL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin1_track_write(&node->data.light.falloff_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } { /*---- LIB3DS_ROLL_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_ROLL_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin1_track_write(&node->data.light.roll_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_L_TARGET_NODE_TAG: { /*---- LIB3DS_POS_TRACK_TAG ----*/ Lib3dsChunk c; c.chunk=LIB3DS_POS_TRACK_TAG; if (!lib3ds_chunk_write_start(&c,io)) { return(LIB3DS_FALSE); } if (!lib3ds_lin3_track_write(&node->data.spot.pos_track,io)) { return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } } break; default: return(LIB3DS_FALSE); } if (!lib3ds_chunk_write_end(&c,io)) { return(LIB3DS_FALSE); } return(LIB3DS_TRUE); }
/*! * Main display function; called whenever the scene needs to be redrawn. */ static void display(void) { Lib3dsNode *c,*t; Lib3dsFloat fov, roll; float near, far, dist; float *campos; float *tgt; Lib3dsMatrix M; Lib3dsCamera *cam; Lib3dsVector v; Lib3dsNode *p; if( file != NULL && file->background.solid.use ) glClearColor(file->background.solid.col[0], file->background.solid.col[1], file->background.solid.col[2], 1.); /* TODO: fog */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if( anti_alias ) glEnable(GL_POLYGON_SMOOTH); else glDisable(GL_POLYGON_SMOOTH); if (!file) { return; } glLightModelfv(GL_LIGHT_MODEL_AMBIENT, file->ambient); c=lib3ds_file_node_by_name(file, camera, LIB3DS_CAMERA_NODE); t=lib3ds_file_node_by_name(file, camera, LIB3DS_TARGET_NODE); if( t != NULL ) tgt = t->data.target.pos; if( c != NULL ) { fov = c->data.camera.fov; roll = c->data.camera.roll; campos = c->data.camera.pos; } if ((cam = lib3ds_file_camera_by_name(file, camera)) == NULL) return; near = cam->near_range; far = cam->far_range; if (c == NULL || t == NULL) { if( c == NULL ) { fov = cam->fov; roll = cam->roll; campos = cam->position; } if( t == NULL ) tgt = cam->target; } glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* KLUDGE alert: OpenGL can't handle a near clip plane of zero, * so if the camera's near plane is zero, we give it a small number. * In addition, many .3ds files I've seen have a far plane that's * much too close and the model gets clipped away. I haven't found * a way to tell OpenGL not to clip the far plane, so we move it * further away. A factor of 10 seems to make all the models I've * seen visible. */ if( near <= 0. ) near = far * .001; gluPerspective( fov, 1.0*gl_width/gl_height, near, far); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(-90, 1.0,0,0); /* User rotates the view about the target point */ lib3ds_vector_sub(v, tgt, campos); dist = lib3ds_vector_length(v); glTranslatef(0.,dist, 0.); glRotatef(view_rotx, 1., 0., 0.); glRotatef(view_roty, 0., 1., 0.); glRotatef(view_rotz, 0., 0., 1.); glTranslatef(0.,-dist, 0.); lib3ds_matrix_camera(M, campos, tgt, roll); glMultMatrixf(&M[0][0]); /* Lights. Set them from light nodes if possible. If not, use the * light objects directly. */ { static const GLfloat a[] = {0.0f, 0.0f, 0.0f, 1.0f}; static GLfloat c[] = {1.0f, 1.0f, 1.0f, 1.0f}; static GLfloat p[] = {0.0f, 0.0f, 0.0f, 1.0f}; Lib3dsLight *l; int li=GL_LIGHT0; for (l=file->lights; l; l=l->next) { glEnable(li); light_update(l); c[0] = l->color[0]; c[1] = l->color[1]; c[2] = l->color[2]; glLightfv(li, GL_AMBIENT, a); glLightfv(li, GL_DIFFUSE, c); glLightfv(li, GL_SPECULAR, c); p[0] = l->position[0]; p[1] = l->position[1]; p[2] = l->position[2]; glLightfv(li, GL_POSITION, p); if (l->spot_light) { p[0] = l->spot[0] - l->position[0]; p[1] = l->spot[1] - l->position[1]; p[2] = l->spot[2] - l->position[2]; glLightfv(li, GL_SPOT_DIRECTION, p); } ++li; } } if( show_object ) { for (p=file->nodes; p!=0; p=p->next) { render_node(p); } } if( show_bounds ) draw_bounds(tgt); if( show_cameras ) { for( cam = file->cameras; cam != NULL; cam = cam->next ) { lib3ds_matrix_camera(M, cam->position, cam->target, cam->roll); lib3ds_matrix_inv(M); glPushMatrix(); glMultMatrixf(&M[0][0]); glScalef(size/20, size/20, size/20); glCallList(cameraList); glPopMatrix(); } } if( show_lights ) { Lib3dsLight *light; for( light = file->lights; light != NULL; light = light->next ) draw_light(light->position, light->color); glMaterialfv(GL_FRONT, GL_EMISSION, black); } glutSwapBuffers(); }
static bool load_keyframes(Lib3dsFile *file, const char *name, Lib3dsNodeTypes type, XFormNode *node) { if(!name || !*name) return false; Lib3dsNode *n = lib3ds_file_node_by_name(file, name, type); if(!n) return false; switch(type) { case LIB3DS_OBJECT_NODE: { Lib3dsObjectData *obj = &n->data.object; std::vector<int> *frames = get_frames(obj); if(!frames) return false; for(int i=0; i<(int)frames->size(); i++) { lib3ds_node_eval(n, (float)(*frames)[i]); Vector3 pos = CONV_VEC3(obj->pos) - CONV_VEC3(obj->pivot); Quaternion rot = CONV_QUAT(obj->rot); Vector3 scl = CONV_VEC3(obj->scl); Keyframe key(PRS(pos, rot, scl), FRAME_TO_TIME((*frames)[i])); node->add_keyframe(key); } } break; case LIB3DS_LIGHT_NODE: { Lib3dsLightData *light = &n->data.light; std::vector<int> *frames = get_frames(light); if(!frames) return false; for(int i=0; i<(int)frames->size(); i++) { lib3ds_node_eval(n, (float)(*frames)[i]); Vector3 pos = CONV_VEC3(light->pos); Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i])); node->add_keyframe(key); } } break; case LIB3DS_CAMERA_NODE: { Lib3dsCameraData *cam = &n->data.camera; std::vector<int> *frames = get_frames(cam); if(!frames) return false; for(int i=0; i<(int)frames->size(); i++) { lib3ds_node_eval(n, (float)(*frames)[i]); Vector3 pos = CONV_VEC3(cam->pos); Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i])); node->add_keyframe(key); } } break; /* case LIB3DS_TARGET_NODE: { Lib3dsCameraData *targ = &n->data.target; std::vector<int> *frames = get_frames(targ); if(!frames) return false; for(int i=0; i<(int)frames->size(); i++) { lib3ds_node_eval(n, (float)(*frames)[i]); Vector3 pos = CONV_VEC3(targ->pos); Keyframe key(PRS(pos, Quaternion()), FRAME_TO_TIME((*frames)[i])); node->add_keyframe(key); } } break; */ default: break; } return true; }
static bool load_objects(Lib3dsFile *file, Scene *scene) { // load meshes unsigned long poly_count = 0; Lib3dsMesh *m = file->meshes; while(m) { Lib3dsNode *node = lib3ds_file_node_by_name(file, m->name, LIB3DS_OBJECT_NODE); if(!node) { warning("object \"%s\" does not have a corresponding node!", m->name); } Vector3 node_pos = node ? CONV_VEC3(node->data.object.pos) : Vector3(); Quaternion node_rot = node ? CONV_QUAT(node->data.object.rot) : Quaternion(); Vector3 node_scl = node ? CONV_VEC3(node->data.object.scl) : Vector3(1,1,1); Vector3 pivot = node ? CONV_VEC3(node->data.object.pivot) : Vector3(); // load the vertices Vertex *varray = new Vertex[m->points]; Vertex *vptr = varray; for(int i=0; i<(int)m->points; i++) { vptr->pos = CONV_VEC3(m->pointL[i].pos) - node_pos; vptr->pos.transform(node_rot); if(m->texels) { vptr->tex[0] = vptr->tex[1] = CONV_TEXCOORD(m->texelL[i]); } vptr++; } if(m->faces) { poly_count += m->faces; // -------- object --------- Object *obj = new Object; obj->set_dynamic(false); obj->name = m->name; obj->set_position(node_pos - pivot); obj->set_rotation(node_rot); obj->set_scaling(node_scl); obj->set_pivot(pivot); // load the polygons Triangle *tarray = new Triangle[m->faces]; Triangle *tptr = tarray; for(int i=0; i<(int)m->faces; i++) { *tptr = CONV_TRIANGLE(m->faceL[i]); tptr->normal = CONV_VEC3(m->faceL[i].normal); tptr->smoothing_group = m->faceL[i].smoothing; tptr++; } // set the geometry data to the object obj->get_mesh_ptr()->set_data(varray, m->points, tarray, m->faces); obj->get_mesh_ptr()->calculate_normals(); delete [] tarray; // load the material load_material(file, m->faceL[0].material, obj->get_material_ptr()); // load the keyframes (if any) if(load_keyframes(file, m->name, LIB3DS_OBJECT_NODE, obj)) { obj->set_position(Vector3()); obj->set_rotation(Quaternion()); obj->set_scaling(Vector3(1, 1, 1)); } scene->add_object(obj); } else { // --------- curve ------------ Curve *curve = new CatmullRomSplineCurve; curve->name = m->name; Vector3 offs = node_pos - pivot; for(int i=0; i<(int)m->points; i++) { curve->add_control_point(varray[i].pos + offs); } scene->add_curve(curve); } delete [] varray; m = m->next; } scene->set_poly_count(poly_count); return true; }
void x3ds_instance::display() { assert(m_def != NULL); if (m_def->m_file == NULL) { return; } //update_material(); // save GL state glPushAttrib (GL_ALL_ATTRIB_BITS); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMatrixMode(GL_PROJECTION); glPushMatrix(); // apply gameSWF matrix rect bound; m_def->get_bound(&bound); matrix m = get_parent()->get_world_matrix(); m.transform(&bound); // get viewport size GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); // int vp_width = vp[2]; int vp_height = vp[3]; bound.twips_to_pixels(); int w = (int) (bound.m_x_max - bound.m_x_min); int h = (int) (bound.m_y_max - bound.m_y_min); int x = (int) bound.m_x_min; int y = (int) bound.m_y_min; glViewport(x, vp_height - y - h, w, h); // set 3D params glClear(GL_DEPTH_BUFFER_BIT); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glCullFace(GL_BACK); glEnable(GL_POLYGON_SMOOTH); // glEnable(GL_BLEND); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); // set GL matrix to identity glMatrixMode(GL_PROJECTION); glLoadIdentity(); assert(m_camera); Lib3dsNode* cnode = lib3ds_file_node_by_name(m_def->m_file, m_camera->name, LIB3DS_CAMERA_NODE); Lib3dsNode* tnode = lib3ds_file_node_by_name(m_def->m_file, m_camera->name, LIB3DS_TARGET_NODE); float* target = tnode ? tnode->data.target.pos : m_camera->target; float view_angle; float roll; float* camera_pos; if (cnode) { view_angle = cnode->data.camera.fov; roll = cnode->data.camera.roll; camera_pos = cnode->data.camera.pos; } else { view_angle = m_camera->fov; roll = m_camera->roll; camera_pos = m_camera->position; } float ffar = m_camera->far_range; float nnear = m_camera->near_range <= 0 ? ffar * .001f : m_camera->near_range; float top = tan(view_angle * 0.5f) * nnear; float bottom = -top; float aspect = 1.3333f; // 4/3 == width /height float left = aspect* bottom; float right = aspect * top; // gluPerspective(fov, aspect, nnear, ffar) ==> glFrustum(left, right, bottom, top, nnear, ffar); // fov * 0.5 = arctan ((top-bottom)*0.5 / near) // Since bottom == -top for the symmetrical projection that gluPerspective() produces, then: // top = tan(fov * 0.5) * near // bottom = -top // Note: fov must be in radians for the above formulae to work with the C math library. // If you have comnputer your fov in degrees (as in the call to gluPerspective()), // then calculate top as follows: // top = tan(fov*3.14159/360.0) * near // The left and right parameters are simply functions of the top, bottom, and aspect: // left = aspect * bottom // right = aspect * top glFrustum(left, right, bottom, top, nnear, ffar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(-90., 1.0, 0., 0.); // apply camera matrix Lib3dsMatrix cmatrix; lib3ds_matrix_camera(cmatrix, camera_pos, target, roll); glMultMatrixf(&cmatrix[0][0]); // apply light set_light(); // draw 3D model for (Lib3dsNode* p = m_def->m_file->nodes; p != 0; p = p->next) { render_node(p); } // restore openGL state glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); }
// apply light // Set them from light nodes if possible. // If not, use the light objects directly. void x3ds_instance::set_light() { glLightModelfv(GL_LIGHT_MODEL_AMBIENT, m_def->m_file->ambient); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glShadeModel(GL_SMOOTH); Lib3dsLight* l = m_def->m_file->lights; for (int gl_light = GL_LIGHT0; gl_light <= GL_LIGHT7; gl_light++) { if (l) { glEnable(gl_light); // default we use light objects directly GLfloat color[4]; color[0] = l->color[0]; color[1] = l->color[1]; color[2] = l->color[2]; color[3] = 1; // default position GLfloat position[4]; position[0] = l->position[0]; position[1] = l->position[1]; position[2] = l->position[2]; position[3] = 1; // try light nodes if possible Lib3dsNode* ln = lib3ds_file_node_by_name(m_def->m_file, l->name, LIB3DS_LIGHT_NODE); if (ln) { color[0] = ln->data.light.col[0]; color[1] = ln->data.light.col[1]; color[2] = ln->data.light.col[2]; position[0] = ln->data.light.pos[0]; position[1] = ln->data.light.pos[1]; position[2] = ln->data.light.pos[2]; } // try spot nodes if possible Lib3dsNode* sn = lib3ds_file_node_by_name(m_def->m_file, l->name, LIB3DS_SPOT_NODE); if (sn) { l->spot[0] = sn->data.spot.pos[0]; l->spot[1] = sn->data.spot.pos[1]; l->spot[2] = sn->data.spot.pos[2]; } static const GLfloat a[] = {0.0f, 0.0f, 0.0f, 1.0f}; glLightfv(gl_light, GL_AMBIENT, a); glLightfv(gl_light, GL_DIFFUSE, color); glLightfv(gl_light, GL_SPECULAR, color); glLightfv(gl_light, GL_POSITION, position); glLightf(gl_light, GL_LINEAR_ATTENUATION, l->attenuation); // glLightf(gl_light, GL_CONSTANT_ATTENUATION, 0); // glLightf(gl_light, GL_QUADRATIC_ATTENUATION, 0); if (l->spot_light) { position[0] = l->spot[0]; position[1] = l->spot[1]; position[2] = l->spot[2]; glLightfv(gl_light, GL_SPOT_DIRECTION, position); glLightf(gl_light, GL_SPOT_CUTOFF, l->fall_off); glLightf(gl_light, GL_SPOT_EXPONENT, 0); // hack } l = l->next; } else { glDisable(gl_light); } } glEnable(GL_LIGHTING); }