/*!
     * \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;
    }
/*!
 * 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]);
}
Exemple #3
0
/*!
 * 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);
    }
  }
}
Exemple #4
0
/*!
 * 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);
        }
    }
}
Exemple #5
0
static void
file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, 
                                int include_meshes, int include_cameras, int include_lights,
                                float bmin[3], float bmax[3], float matrix[4][4]) {
    switch (node->type) {
        case LIB3DS_NODE_MESH_INSTANCE:
            if (include_meshes) {
                int index;
                Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;

                index = lib3ds_file_mesh_by_name(file, n->instance_name);
                if (index < 0)
                    index = lib3ds_file_mesh_by_name(file, node->name);
                if (index >= 0) {
                    Lib3dsMesh *mesh;
                    float inv_matrix[4][4], M[4][4];
                    float v[3];
                    int i;

                    mesh = file->meshes[index];
                    lib3ds_matrix_copy(inv_matrix, mesh->matrix);
                    lib3ds_matrix_inv(inv_matrix);
                    lib3ds_matrix_mult(M, matrix, node->matrix);
                    lib3ds_matrix_translate(M, -n->pivot[0], -n->pivot[1], -n->pivot[2]);
                    lib3ds_matrix_mult(M, M, inv_matrix);

                    for (i = 0; i < mesh->nvertices; ++i) {
                        lib3ds_vector_transform(v, M, mesh->vertices[i]);
                        lib3ds_vector_min(bmin, v);
                        lib3ds_vector_max(bmax, v);
                    }
                }
            }
            break;

        case LIB3DS_NODE_CAMERA:
        case LIB3DS_NODE_CAMERA_TARGET:
            if (include_cameras) {
                float z[3], v[3];
                float M[4][4];
                lib3ds_matrix_mult(M, matrix, node->matrix);
                lib3ds_vector_zero(z);
                lib3ds_vector_transform(v, M, z);
                lib3ds_vector_min(bmin, v);
                lib3ds_vector_max(bmax, v);
            }
            break;

        case LIB3DS_NODE_OMNILIGHT:
        case LIB3DS_NODE_SPOTLIGHT:
        case LIB3DS_NODE_SPOTLIGHT_TARGET:
            if (include_lights) {
                float z[3], v[3];
                float M[4][4];
                lib3ds_matrix_mult(M, matrix, node->matrix);
                lib3ds_vector_zero(z);
                lib3ds_vector_transform(v, M, z);
                lib3ds_vector_min(bmin, v);
                lib3ds_vector_max(bmax, v);
            }
            break;
    }
    {
        Lib3dsNode *p = node->childs;
        while (p) {
            file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, matrix);
            p = p->next;
        }
    }
}
Exemple #6
0
void write_mesh(FILE *o, Lib3dsFile *f, Lib3dsMeshInstanceNode *node) {
    float (*orig_vertices)[3];
    int export_texcos;
    int export_normals;
    int i, j;
    Lib3dsMesh *mesh;
        
    mesh = lib3ds_file_mesh_for_node(f, (Lib3dsNode*)node);
    if (!mesh || !mesh->vertices) return;

    fprintf(o, "# object %s\n", node->base.name);
    fprintf(o, "g %s\n", node->instance_name[0]? node->instance_name : node->base.name);

    orig_vertices = (float(*)[3])malloc(sizeof(float) * 3 * mesh->nvertices);
    memcpy(orig_vertices, mesh->vertices, sizeof(float) * 3 * mesh->nvertices);
     {
         float inv_matrix[4][4], M[4][4];
         float tmp[3];
         int i;
 
         lib3ds_matrix_copy(M, node->base.matrix);
         lib3ds_matrix_translate(M, -node->pivot[0], -node->pivot[1], -node->pivot[2]);
         lib3ds_matrix_copy(inv_matrix, mesh->matrix);
         lib3ds_matrix_inv(inv_matrix);
         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);
         }
     }

    export_texcos = (mesh->texcos != 0);
    export_normals = (mesh->faces != 0);

    for (i = 0; i < mesh->nvertices; ++i) {
        fprintf(o, "v %f %f %f\n", mesh->vertices[i][0], 
                                   mesh->vertices[i][1], 
                                   mesh->vertices[i][2]);
    }
    fprintf(o, "# %d vertices\n", mesh->nvertices);

    if (export_texcos) {
        for (i = 0; i < mesh->nvertices; ++i) {
            fprintf(o, "vt %f %f\n", mesh->texcos[i][0], 
                                     mesh->texcos[i][1]);
        }
        fprintf(o, "# %d texture vertices\n", mesh->nvertices);
    }

    if (export_normals) {
        float (*normals)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces);
        lib3ds_mesh_calculate_vertex_normals(mesh, normals);
        for (i = 0; i < 3 * mesh->nfaces; ++i) {
            fprintf(o, "vn %f %f %f\n", normals[i][0],
                                        normals[i][1],
                                        normals[i][2]);
        }
        free(normals);  
        fprintf(o, "# %d normals\n", 3 * mesh->nfaces);
    }

    {
        int mat_index = -1;
        for (i = 0; i < mesh->nfaces; ++i) {
            if (mat_index != mesh->faces[i].material) {
                mat_index = mesh->faces[i].material;
                if (mat_index != -1) {
                    fprintf(o, "usemtl %s\n", f->materials[mat_index]->name);
                }
            }

            fprintf(o, "f ");
            for (j = 0; j < 3; ++j) {
                fprintf(o, "%d", mesh->faces[i].index[j] + max_vertices + 1);
                if (export_texcos) {
                    fprintf(o, "/%d", mesh->faces[i].index[j] + max_texcos + 1);
                } else if (export_normals) {
                    fprintf(o, "/");
                }
                if (export_normals) {
                    fprintf(o, "/%d", 3 * i + j + max_normals + 1);
                }
                if (j < 3) {
                    fprintf(o, " ");
                }
            }
            fprintf(o, "\n");
        }
    }

    max_vertices += mesh->nvertices;
    if (export_texcos) 
        max_texcos += mesh->nvertices;
    if (export_normals) 
        max_normals += 3 * mesh->nfaces;
    
    memcpy(mesh->vertices, orig_vertices, sizeof(float) * 3 * mesh->nvertices);
    free(orig_vertices);
}
std::vector<CL_Lib3dsMesh> CL_Lib3dsFile::export_meshes(Lib3dsNode *node)
{
	if (node == 0)
	{
		lib3ds_file_eval(file, 0.0f);
		node = file->nodes;
	}

	std::vector<CL_Lib3dsMesh> meshes;
	for (; node; node = node->next)
	{
		if (node->type == LIB3DS_NODE_MESH_INSTANCE)
		{
			Lib3dsMeshInstanceNode *instance_node = (Lib3dsMeshInstanceNode *) node;
			Lib3dsMesh *mesh = lib3ds_file_mesh_for_node(file, (Lib3dsNode*)node);
			if (mesh && mesh->vertices)
			{
				float inv_matrix[4][4], M[4][4];
				lib3ds_matrix_copy(M, instance_node->base.matrix);
				lib3ds_matrix_translate(M, -instance_node->pivot[0], -instance_node->pivot[1], -instance_node->pivot[2]);
				lib3ds_matrix_copy(inv_matrix, mesh->matrix);
				lib3ds_matrix_inv(inv_matrix);
				lib3ds_matrix_mult(M, M, inv_matrix);

				std::vector<CL_Vec3f> positions;
				for (int i = 0; i < mesh->nvertices; ++i)
				{
					float position[3];
					lib3ds_vector_transform(position, M, mesh->vertices[i]);
					positions.push_back(CL_Vec3f(position[0], position[1], position[2]));
				}

				std::vector<CL_Vec2f> texcoords;
				if (mesh->texcos)
				{
					for (int i = 0; i < mesh->nvertices; ++i)
					{
						float tx = mesh->texcos[i][0];
						float ty = mesh->texcos[i][1];
						texcoords.push_back(CL_Vec2f(tx, ty));
					}
				}

				std::vector<CL_Vec3f> normals;
				if (mesh->faces && mesh->nfaces > 0)
				{
			        float (*normals_array)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces);
					lib3ds_mesh_calculate_vertex_normals(mesh, normals_array);
					for (int i = 0; i < 3 * mesh->nfaces; ++i)
					{
						normals.push_back(CL_Vec3f(normals_array[i][0], normals_array[i][1], normals_array[i][2]));
					}
					free(normals_array);
				}

				CL_Lib3dsMesh mesh_object;
				for (int i = 0; i < mesh->nfaces; ++i)
				{
					int material_index = mesh->faces[i].material;
					mesh_object.face_materials.push_back(material_index);

					for (int j = 0; j < 3; ++j)
					{
						int vertex_index = mesh->faces[i].index[j];
						mesh_object.positions.push_back(positions[vertex_index]);
						if (!texcoords.empty())
							mesh_object.texcooords.push_back(texcoords[vertex_index]);
						if (!normals.empty())
							mesh_object.normals.push_back(normals[i*3+j]);
					}
				}

				meshes.push_back(mesh_object);
			}

			if (node->childs)
			{
				std::vector<CL_Lib3dsMesh> child_meshes = export_meshes(node->childs);
				meshes.insert(meshes.end(), child_meshes.begin(), child_meshes.end());
			}
		}
	}

	return meshes;
}