/*! * \ingroup matrix */ void lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos, Lib3dsVector tgt, Lib3dsFloat roll) { Lib3dsMatrix M,R; Lib3dsVector x, y, z; lib3ds_vector_sub(y, tgt, pos); lib3ds_vector_normalize(y); z[0] = 0; z[1] = 0; z[2] = 1.0; lib3ds_vector_cross(x, y, z); lib3ds_vector_cross(z, x, y); lib3ds_vector_normalize(x); lib3ds_vector_normalize(y); lib3ds_matrix_identity(M); M[0][0] = x[0]; M[1][0] = x[1]; M[2][0] = x[2]; M[0][1] = y[0]; M[1][1] = y[1]; M[2][1] = y[2]; M[0][2] = z[0]; M[1][2] = z[1]; M[2][2] = z[2]; lib3ds_matrix_identity(R); lib3ds_matrix_rotate_y(R, roll); lib3ds_matrix_mul(matrix, R,M); lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]); }
void x3ds_definition::ensure_camera() { if (m_file->cameras == NULL) { // Fabricate camera Lib3dsCamera* camera = lib3ds_camera_new("Perscpective"); float size; Lib3dsVector bmin, bmax; get_bounding_center(bmin, bmax, camera->target, &size); memcpy(camera->position, camera->target, sizeof(camera->position)); camera->position[0] = bmax[0] + 0.75f * size; camera->position[1] = bmin[1] - 0.75f * size; camera->position[2] = bmax[2] + 0.75f * size; // hack Lib3dsMatrix m; lib3ds_matrix_identity(m); lib3ds_matrix_rotate_z(m, 1.6f); // PI/2 lib3ds_matrix_rotate_y(m, 0.3f); lib3ds_vector_transform(camera->position, m, camera->position); camera->near_range = (camera->position[0] - bmax[0] ) * 0.5f; camera->far_range = (camera->position[0] - bmin[0] ) * 3.0f; lib3ds_file_insert_camera(m_file, camera); } }
/*! * Create and return a new ambient node. * * The node is returned with an identity matrix. All other fields * are zero. * * \return Lib3dsNode * * \ingroup node */ Lib3dsNode* lib3ds_node_new_ambient() { Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); node->type=LIB3DS_AMBIENT_NODE; lib3ds_matrix_identity(node->matrix); return(node); }
/*! * Create and return a new target node. * * The node is returned with an identity matrix. All other fields * are zero. * * \return Lib3dsNode * * \ingroup node */ Lib3dsNode* lib3ds_node_new_target() { Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); node->type=LIB3DS_TARGET_NODE; lib3ds_matrix_identity(node->matrix); return(node); }
/*! * Create and return a new object node. * * The node is returned with an identity matrix. All other fields * are zero. * * \return Lib3dsNode * * \ingroup node */ Lib3dsNode* lib3ds_node_new_object() { Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); node->type=LIB3DS_OBJECT_NODE; lib3ds_matrix_identity(node->matrix); return(node); }
/*! * Create and return a new camera node. * * The node is returned with an identity matrix. All other fields * are zero. * * \return Lib3dsNode * * \ingroup node */ Lib3dsNode* lib3ds_node_new_camera() { Lib3dsNode *node=(Lib3dsNode*)calloc(sizeof(Lib3dsNode), 1); node->type=LIB3DS_CAMERA_NODE; lib3ds_matrix_identity(node->matrix); return(node); }
/*! * See \ref Loader3ds::loadFromFile */ dcollide::Proxy* Loader3dsInternal::loadFromFile(dcollide::World* world, const char* fileName, dcollide::ProxyTypes proxyType) { mData->mProxy2Transformation.clear(); mData->mProxy2TextureInformation.clear(); if (!fileName) { // TODO: exception? return 0; } mFile = lib3ds_file_load(fileName); if (!mFile) { std::cout << dc_funcinfo << "unable to load " << fileName << std::endl; return 0; } // AB: some files don't store nodes and just want exactly one node per mesh. // atm we don't support that. if (!mFile->nodes) { std::cout << dc_funcinfo << "File " << fileName << " does not contain any nodes. mesh-only files not supported currently." << std::endl; lib3ds_file_free(mFile); mFile = 0; return 0; } // 3ds stores several frames, we want the first lib3ds_file_eval(mFile, 0); if (!checkUniqueMeshMaterial()) { std::cerr << dc_funcinfo << "the file " << fileName << " contains at least one mesh with different materials. this is not supported by this modelloader, only the first material will be used!" << std::endl; } dcollide::Proxy* topObject = world->createProxy(proxyType); mData->mProxy2Transformation.insert(std::make_pair(topObject, Loader3ds::TransformationNode())); Lib3dsMatrix identityMatrix; lib3ds_matrix_identity(identityMatrix); Lib3dsNode* node = mFile->nodes; while (node) { // node->type can be object, light, camera, ... // -> only object nodes are relevant to us if (node->type == LIB3DS_OBJECT_NODE) { if (!loadNode(world, topObject, node, &identityMatrix)) { std::cerr << dc_funcinfo << "Loading node from " << fileName << " failed" << std::endl; // TODO: is MyObjectNode::mProxy being deleted? delete topObject; lib3ds_file_free(mFile); mFile = 0; return 0; } } node = node->next; } lib3ds_file_free(mFile); mFile = 0; return topObject; }
/*! * Compute a camera matrix based on position, target and roll. * * Generates a translate/rotate matrix that maps world coordinates * to camera coordinates. Resulting matrix does not include perspective * transform. * * \param matrix Destination matrix. * \param pos Camera position * \param tgt Camera target * \param roll Roll angle * * \ingroup matrix */ void lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos, Lib3dsVector tgt, Lib3dsFloat roll) { Lib3dsMatrix M; Lib3dsVector x, y, z; lib3ds_vector_sub(y, tgt, pos); lib3ds_vector_normalize(y); if (y[0] != 0. || y[1] != 0) { z[0] = 0; z[1] = 0; z[2] = 1.0; } else { /* Special case: looking straight up or down z axis */ z[0] = -1.0; z[1] = 0; z[2] = 0; } lib3ds_vector_cross(x, y, z); lib3ds_vector_cross(z, x, y); lib3ds_vector_normalize(x); lib3ds_vector_normalize(z); lib3ds_matrix_identity(M); M[0][0] = x[0]; M[1][0] = x[1]; M[2][0] = x[2]; M[0][1] = y[0]; M[1][1] = y[1]; M[2][1] = y[2]; M[0][2] = z[0]; M[1][2] = z[1]; M[2][2] = z[2]; lib3ds_matrix_identity(matrix); lib3ds_matrix_rotate_y(matrix, roll); lib3ds_matrix_mult(matrix, M); lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]); }
/*! * Compute a camera matrix based on position, target and roll. * * Generates a translate/rotate matrix that maps world coordinates * to camera coordinates. Resulting matrix does not include perspective * transform. * * \param matrix Destination matrix. * \param pos Camera position * \param tgt Camera target * \param roll Roll angle */ void lib3ds_matrix_camera(float matrix[4][4], float pos[3], float tgt[3], float roll) { float M[4][4]; float x[3], y[3], z[3]; lib3ds_vector_sub(y, tgt, pos); lib3ds_vector_normalize(y); if (y[0] != 0. || y[1] != 0) { z[0] = 0; z[1] = 0; z[2] = 1.0; } else { /* Special case: looking straight up or down z axis */ z[0] = -1.0; z[1] = 0; z[2] = 0; } lib3ds_vector_cross(x, y, z); lib3ds_vector_cross(z, x, y); lib3ds_vector_normalize(x); lib3ds_vector_normalize(z); lib3ds_matrix_identity(M); M[0][0] = x[0]; M[1][0] = x[1]; M[2][0] = x[2]; M[0][1] = y[0]; M[1][1] = y[1]; M[2][1] = y[2]; M[0][2] = z[0]; M[1][2] = z[1]; M[2][2] = z[2]; lib3ds_matrix_identity(matrix); lib3ds_matrix_rotate(matrix, roll, 0, 1, 0); lib3ds_matrix_mult(matrix, matrix, M); lib3ds_matrix_translate(matrix, -pos[0], -pos[1], -pos[2]); }
/*! * Create and return a new empty mesh object. * * Mesh is initialized with the name and an identity matrix; all * other fields are zero. * * See Lib3dsFaceFlag for definitions of per-face flags. * * \param name Mesh name. Must not be NULL. Must be < 64 characters. * * \return mesh object or NULL on error. */ Lib3dsMesh* lib3ds_mesh_new(const char *name) { Lib3dsMesh *mesh; assert(name); assert(strlen(name) < 64); mesh = (Lib3dsMesh*) calloc(sizeof(Lib3dsMesh), 1); if (!mesh) { return (0); } stringcopyfixedsize(mesh->name, name); lib3ds_matrix_identity(mesh->matrix); mesh->map_type = LIB3DS_MAP_NONE; return (mesh); }
/*! * Create and return a new empty mesh object. * * Mesh is initialized with the name and an identity matrix; all * other fields are zero. * * See Lib3dsFaceFlag for definitions of per-face flags. * * \param name Mesh name. Must not be NULL. Must be < 64 characters. * * \return mesh object or NULL on error. * * \ingroup mesh */ Lib3dsMesh* lib3ds_mesh_new(const char *name) { Lib3dsMesh *mesh; ASSERT(name); ASSERT(strlen(name)<64); mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1); if (!mesh) { return(0); } strcpy(mesh->name, name); lib3ds_matrix_identity(mesh->matrix); mesh->map_data.maptype=LIB3DS_MAP_NONE; return(mesh); }
/*! * \internal * * The objects created as children of \p parent will \em not be rotated or * translated correctly. Instead the required transformations are stored and * provided to the user, see \ref Loader3ds::getTransformationNodes */ bool Loader3dsInternal::loadNode(dcollide::World* world, dcollide::Proxy* parent, Lib3dsNode* node, Lib3dsMatrix* parentTranslateRotateMatrix) { if (!parent || !node) { return false; } if (node->type != LIB3DS_OBJECT_NODE) { return false; } Lib3dsObjectData* data = &node->data.object; Lib3dsMatrix translateRotateMatrix; lib3ds_matrix_copy(translateRotateMatrix, *parentTranslateRotateMatrix); lib3ds_matrix_translate(translateRotateMatrix, data->pos); lib3ds_matrix_rotate(translateRotateMatrix, data->rot); dcollide::Shape* shape = createShape(node, &translateRotateMatrix); dcollide::Proxy* object = world->createProxy(shape); mData->mProxy2TextureInformation.insert(std::make_pair(object, loadTextureInformation(node))); dcollide::Vector3 scale(data->scl[0], data->scl[1], data->scl[2]); dcollide::Vector3 translation(data->pos[0], data->pos[1], data->pos[2]); Lib3dsMatrix lib3dsRotationMatrix; lib3ds_matrix_identity(lib3dsRotationMatrix); lib3ds_matrix_rotate(lib3dsRotationMatrix, data->rot); dcollide::Matrix rotation(&lib3dsRotationMatrix[0][0]); Loader3ds::TransformationNode transformation; transformation.translation = translation; transformation.rotation = rotation; mData->mProxy2Transformation.insert(std::make_pair(object, transformation)); for (Lib3dsNode* n = node->childs; n; n = n->next) { if (!loadNode(world, object, n, &translateRotateMatrix)) { std::cerr << "Failed loading node " << n->name << std::endl; // TODO: delete object->getProxy() ? delete object; return false; } } parent->addChild(object); return true; }
void lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, int include_meshes, int include_cameras,int include_lights, float bmin[3], float bmax[3], float matrix[4][4]) { Lib3dsNode *p; float M[4][4]; if (matrix) { lib3ds_matrix_copy(M, matrix); } else { lib3ds_matrix_identity(M); } bmin[0] = bmin[1] = bmin[2] = FLT_MAX; bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; p = file->nodes; while (p) { file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, M); p = p->next; } }
void lib3ds_mesh_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; uint16_t chunk; lib3ds_chunk_read_start(&c, CHK_N_TRI_OBJECT, io); while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { switch (chunk) { case CHK_MESH_MATRIX: { int i, j; lib3ds_matrix_identity(mesh->matrix); for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { mesh->matrix[i][j] = lib3ds_io_read_float(io); } } break; } case CHK_MESH_COLOR: { mesh->color = lib3ds_io_read_byte(io); break; } case CHK_POINT_ARRAY: { int i; uint16_t nvertices = lib3ds_io_read_word(io); lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, mesh->vflags != NULL); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_io_read_vector(io, mesh->vertices[i]); } break; } case CHK_POINT_FLAG_ARRAY: { int i; uint16_t nflags = lib3ds_io_read_word(io); uint16_t nvertices = (mesh->nvertices >= nflags)? mesh->nvertices : nflags; lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, 1); for (i = 0; i < nflags; ++i) { mesh->vflags[i] = lib3ds_io_read_word(io); } break; } case CHK_FACE_ARRAY: { lib3ds_chunk_read_reset(&c, io); face_array_read(file, mesh, io); break; } case CHK_MESH_TEXTURE_INFO: { int i, j; //FIXME: mesh->map_type = lib3ds_io_read_word(io); for (i = 0; i < 2; ++i) { mesh->map_tile[i] = lib3ds_io_read_float(io); } for (i = 0; i < 3; ++i) { mesh->map_pos[i] = lib3ds_io_read_float(io); } mesh->map_scale = lib3ds_io_read_float(io); lib3ds_matrix_identity(mesh->map_matrix); for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { mesh->map_matrix[i][j] = lib3ds_io_read_float(io); } } for (i = 0; i < 2; ++i) { mesh->map_planar_size[i] = lib3ds_io_read_float(io); } mesh->map_cylinder_height = lib3ds_io_read_float(io); break; } case CHK_TEX_VERTS: { int i; uint16_t ntexcos = lib3ds_io_read_word(io); uint16_t nvertices = (mesh->nvertices >= ntexcos)? mesh->nvertices : ntexcos;; if (!mesh->texcos) { lib3ds_mesh_resize_vertices(mesh, nvertices, 1, mesh->vflags != NULL); } for (i = 0; i < ntexcos; ++i) { mesh->texcos[i][0] = lib3ds_io_read_float(io); mesh->texcos[i][1] = lib3ds_io_read_float(io); } break; } default: lib3ds_chunk_unknown(chunk, io); } } if (lib3ds_matrix_det(mesh->matrix) < 0.0) { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ float inv_matrix[4][4], M[4][4]; float tmp[3]; int i; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(tmp, M, mesh->vertices[i]); lib3ds_vector_copy(mesh->vertices[i], tmp); } } lib3ds_chunk_read_end(&c, io); }
/*! * \ingroup mesh */ Lib3dsBool lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; Lib3dsWord chunk; if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) { return(LIB3DS_FALSE); } while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { switch (chunk) { case LIB3DS_MESH_MATRIX: { int i,j; lib3ds_matrix_identity(mesh->matrix); for (i=0; i<4; i++) { for (j=0; j<3; j++) { mesh->matrix[i][j]=lib3ds_io_read_float(io); } } } break; case LIB3DS_MESH_COLOR: { mesh->color=lib3ds_io_read_byte(io); } break; case LIB3DS_POINT_ARRAY: { unsigned i,j; unsigned points; lib3ds_mesh_free_point_list(mesh); points=lib3ds_io_read_word(io); if (points) { if (!lib3ds_mesh_new_point_list(mesh, points)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->points; ++i) { for (j=0; j<3; ++j) { mesh->pointL[i].pos[j]=lib3ds_io_read_float(io); } } ASSERT((!mesh->flags) || (mesh->points==mesh->flags)); ASSERT((!mesh->texels) || (mesh->points==mesh->texels)); } } break; case LIB3DS_POINT_FLAG_ARRAY: { unsigned i; unsigned flags; lib3ds_mesh_free_flag_list(mesh); flags=lib3ds_io_read_word(io); if (flags) { if (!lib3ds_mesh_new_flag_list(mesh, flags)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->flags; ++i) { mesh->flagL[i]=lib3ds_io_read_word(io); } ASSERT((!mesh->points) || (mesh->flags==mesh->points)); ASSERT((!mesh->texels) || (mesh->flags==mesh->texels)); } } break; case LIB3DS_FACE_ARRAY: { lib3ds_chunk_read_reset(&c, io); if (!face_array_read(mesh, io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_MESH_TEXTURE_INFO: { int i,j; for (i=0; i<2; ++i) { mesh->map_data.tile[i]=lib3ds_io_read_float(io); } for (i=0; i<3; ++i) { mesh->map_data.pos[i]=lib3ds_io_read_float(io); } mesh->map_data.scale=lib3ds_io_read_float(io); lib3ds_matrix_identity(mesh->map_data.matrix); for (i=0; i<4; i++) { for (j=0; j<3; j++) { mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io); } } for (i=0; i<2; ++i) { mesh->map_data.planar_size[i]=lib3ds_io_read_float(io); } mesh->map_data.cylinder_height=lib3ds_io_read_float(io); } break; case LIB3DS_TEX_VERTS: { unsigned i; unsigned texels; lib3ds_mesh_free_texel_list(mesh); texels=lib3ds_io_read_word(io); if (texels) { if (!lib3ds_mesh_new_texel_list(mesh, texels)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->texels; ++i) { mesh->texelL[i][0]=lib3ds_io_read_float(io); mesh->texelL[i][1]=lib3ds_io_read_float(io); } ASSERT((!mesh->points) || (mesh->texels==mesh->points)); ASSERT((!mesh->flags) || (mesh->texels==mesh->flags)); } } break; default: lib3ds_chunk_unknown(chunk); } } { unsigned j; for (j=0; j<mesh->faces; ++j) { ASSERT(mesh->faceL[j].points[0]<mesh->points); ASSERT(mesh->faceL[j].points[1]<mesh->points); ASSERT(mesh->faceL[j].points[2]<mesh->points); lib3ds_vector_normal( mesh->faceL[j].normal, mesh->pointL[mesh->faceL[j].points[0]].pos, mesh->pointL[mesh->faceL[j].points[1]].pos, mesh->pointL[mesh->faceL[j].points[2]].pos ); } } if (lib3ds_matrix_det(mesh->matrix) < 0.0) { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ Lib3dsMatrix inv_matrix, M; Lib3dsVector tmp; unsigned i; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, inv_matrix); for (i=0; i<mesh->points; ++i) { lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos); lib3ds_vector_copy(mesh->pointL[i].pos, tmp); } } lib3ds_chunk_read_end(&c, io); return(LIB3DS_TRUE); }
/*! * Evaluate an animation node. * * Recursively sets node and its children to their appropriate values * for this point in the animation. * * \param node Node to be evaluated. * \param t time value, between 0. and file->frames * * \ingroup node */ void lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t) { ASSERT(node); switch (node->type) { case LIB3DS_UNKNOWN_NODE: { ASSERT(LIB3DS_FALSE); } break; case LIB3DS_AMBIENT_NODE: { Lib3dsAmbientData *n=&node->data.ambient; if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_lin3_track_eval(&n->col_track, n->col, t); } break; case LIB3DS_OBJECT_NODE: { Lib3dsMatrix M; Lib3dsObjectData *n=&node->data.object; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_quat_track_eval(&n->rot_track, n->rot, t); if (n->scl_track.keyL) { lib3ds_lin3_track_eval(&n->scl_track, n->scl, t); } else { n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; } lib3ds_bool_track_eval(&n->hide_track, &n->hide, t); lib3ds_morph_track_eval(&n->morph_track, n->morph, t); lib3ds_matrix_identity(M); lib3ds_matrix_translate(M, n->pos); lib3ds_matrix_rotate(M, n->rot); lib3ds_matrix_scale(M, n->scl); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); lib3ds_matrix_mult(node->matrix, M); } else { lib3ds_matrix_copy(node->matrix, M); } } break; case LIB3DS_CAMERA_NODE: { Lib3dsCameraData *n=&node->data.camera; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_lin1_track_eval(&n->fov_track, &n->fov, t); lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_TARGET_NODE: { Lib3dsTargetData *n=&node->data.target; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_LIGHT_NODE: { Lib3dsLightData *n=&node->data.light; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_lin3_track_eval(&n->col_track, n->col, t); lib3ds_lin1_track_eval(&n->hotspot_track, &n->hotspot, t); lib3ds_lin1_track_eval(&n->falloff_track, &n->falloff, t); lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_SPOT_NODE: { Lib3dsSpotData *n=&node->data.spot; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; } { Lib3dsNode *p; for (p=node->childs; p!=0; p=p->next) { lib3ds_node_eval(p, t); } } }
/*! * Evaluate an animation node. * * Recursively sets node and its children to their appropriate values * for this point in the animation. * * \param node Node to be evaluated. * \param t time value, between 0. and file->frames */ void lib3ds_node_eval(Lib3dsNode *node, float t) { assert(node); switch (node->type) { case LIB3DS_NODE_AMBIENT_COLOR: { Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_track_eval_vector(&n->color_track, n->color, t); break; } case LIB3DS_NODE_MESH_INSTANCE: { float M[4][4]; Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_quat(&n->rot_track, n->rot, t); if (n->scl_track.nkeys) { lib3ds_track_eval_vector(&n->scl_track, n->scl, t); } else { n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; } lib3ds_track_eval_bool(&n->hide_track, &n->hide, t); lib3ds_matrix_identity(M); lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]); lib3ds_matrix_rotate_quat(M, n->rot); lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]); if (node->parent) { lib3ds_matrix_mult(node->matrix, node->parent->matrix, M); } else { lib3ds_matrix_copy(node->matrix, M); } break; } case LIB3DS_NODE_CAMERA: { Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_float(&n->fov_track, &n->fov, t); lib3ds_track_eval_float(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_CAMERA_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_OMNILIGHT: { Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_vector(&n->color_track, n->color, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_SPOTLIGHT: { Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_vector(&n->color_track, n->color, t); lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t); lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t); lib3ds_track_eval_float(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_SPOTLIGHT_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } } { Lib3dsNode *p; for (p = node->childs; p != 0; p = p->next) { lib3ds_node_eval(p, t); } } }
/*! * Create and return a new node object. * * The node is returned with an identity matrix. All other fields * are zero. * * \return Lib3dsNode */ Lib3dsNode* lib3ds_node_new(Lib3dsNodeType type) { Lib3dsNode *node; switch (type) { case LIB3DS_NODE_AMBIENT_COLOR: { Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)calloc(sizeof(Lib3dsAmbientColorNode), 1); node = (Lib3dsNode*)n; strcpy(node->name, "$AMBIENT$"); n->color_track.type = LIB3DS_TRACK_VECTOR; break; } case LIB3DS_NODE_MESH_INSTANCE: { Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)calloc(sizeof(Lib3dsMeshInstanceNode), 1); node = (Lib3dsNode*)n; strcpy(node->name, "$$$DUMMY"); n->pos_track.type = LIB3DS_TRACK_VECTOR; n->scl_track.type = LIB3DS_TRACK_VECTOR; n->rot_track.type = LIB3DS_TRACK_QUAT; n->hide_track.type = LIB3DS_TRACK_BOOL; break; } case LIB3DS_NODE_CAMERA: { Lib3dsCameraNode *n = (Lib3dsCameraNode*)calloc(sizeof(Lib3dsCameraNode), 1); node = (Lib3dsNode*)n; n->pos_track.type = LIB3DS_TRACK_VECTOR; n->fov_track.type = LIB3DS_TRACK_FLOAT; n->roll_track.type = LIB3DS_TRACK_FLOAT; break; } case LIB3DS_NODE_CAMERA_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); node = (Lib3dsNode*)n; n->pos_track.type = LIB3DS_TRACK_VECTOR; break; } case LIB3DS_NODE_OMNILIGHT: { Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)calloc(sizeof(Lib3dsOmnilightNode), 1); node = (Lib3dsNode*)n; n->pos_track.type = LIB3DS_TRACK_VECTOR; n->color_track.type = LIB3DS_TRACK_VECTOR; break; } case LIB3DS_NODE_SPOTLIGHT: { Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)calloc(sizeof(Lib3dsSpotlightNode), 1); node = (Lib3dsNode*)n; n->pos_track.type = LIB3DS_TRACK_VECTOR; n->color_track.type = LIB3DS_TRACK_VECTOR; n->hotspot_track.type = LIB3DS_TRACK_FLOAT; n->falloff_track.type = LIB3DS_TRACK_FLOAT; n->roll_track.type = LIB3DS_TRACK_FLOAT; break; } case LIB3DS_NODE_SPOTLIGHT_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1); node = (Lib3dsNode*)n; n->pos_track.type = LIB3DS_TRACK_VECTOR; break; } default: assert(0); return NULL; } node->type = type; node->node_id = 65535; node->user_id = 65535; lib3ds_matrix_identity(node->matrix); return node; }