/*! * Free a mesh object and all of its resources. * * \param mesh Mesh object to be freed. */ void lib3ds_mesh_free(Lib3dsMesh *mesh) { lib3ds_mesh_resize_vertices(mesh, 0, 0, 0); lib3ds_mesh_resize_faces(mesh, 0); memset(mesh, 0, sizeof(Lib3dsMesh)); free(mesh); }
static void face_array_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; uint16_t chunk; int i; uint16_t nfaces; lib3ds_chunk_read_start(&c, CHK_FACE_ARRAY, io); lib3ds_mesh_resize_faces(mesh, 0); nfaces = lib3ds_io_read_word(io); if (nfaces) { lib3ds_mesh_resize_faces(mesh, nfaces); for (i = 0; i < nfaces; ++i) { mesh->faces[i].index[0] = lib3ds_io_read_word(io); mesh->faces[i].index[1] = lib3ds_io_read_word(io); mesh->faces[i].index[2] = lib3ds_io_read_word(io); mesh->faces[i].flags = lib3ds_io_read_word(io); } lib3ds_chunk_read_tell(&c, io); while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { switch (chunk) { case CHK_MSH_MAT_GROUP: { char name[64]; unsigned n; unsigned i; int index; int material; lib3ds_io_read_string(io, name, 64); material = lib3ds_file_material_by_name(file, name); n = lib3ds_io_read_word(io); for (i = 0; i < n; ++i) { index = lib3ds_io_read_word(io); if (index < mesh->nfaces) { mesh->faces[index].material = material; } else { // TODO warning } } break; } case CHK_SMOOTH_GROUP: { int i; for (i = 0; i < mesh->nfaces; ++i) { mesh->faces[i].smoothing_group = lib3ds_io_read_dword(io); } break; } case CHK_MSH_BOXMAP: { lib3ds_io_read_string(io, mesh->box_front, 64); lib3ds_io_read_string(io, mesh->box_back, 64); lib3ds_io_read_string(io, mesh->box_left, 64); lib3ds_io_read_string(io, mesh->box_right, 64); lib3ds_io_read_string(io, mesh->box_top, 64); lib3ds_io_read_string(io, mesh->box_bottom, 64); break; } default: lib3ds_chunk_unknown(chunk,io); } } } lib3ds_chunk_read_end(&c, io); }
int main(int argc, char **argv) { Lib3dsFile *file = lib3ds_file_new(); file->frames = 360; { Lib3dsMaterial *mat = lib3ds_material_new("c_tex"); lib3ds_file_insert_material(file, mat, -1); strcpy(mat->texture1_map.name, "cube.tga"); mat->texture1_map.percent = 1.0; mat = lib3ds_material_new("c_red"); lib3ds_file_insert_material(file, mat, -1); mat->diffuse[0] = 1.0; mat->diffuse[1] = 0.0; mat->diffuse[2] = 0.0; mat = lib3ds_material_new("c_blue"); lib3ds_file_insert_material(file, mat, -1); mat->diffuse[0] = 0.0; mat->diffuse[1] = 0.0; mat->diffuse[2] = 1.0; } { int i, j; Lib3dsMesh *mesh = lib3ds_mesh_new("cube"); Lib3dsMeshInstanceNode *inst; lib3ds_file_insert_mesh(file, mesh, -1); lib3ds_mesh_resize_vertices(mesh, 8, 1, 0); for (i = 0; i < 8; ++i) { lib3ds_vector_copy(mesh->vertices[i], g_vertices[i]); mesh->texcos[i][0] = g_texcoords[i][0]; mesh->texcos[i][1] = g_texcoords[i][1]; } lib3ds_mesh_resize_faces(mesh, 12); for (i = 0; i < 12; ++i) { for (j = 0; j < 3; ++j) { mesh->faces[i].index[j] = g_indices[i][j]; } } for (i = 0; i < 8; ++i) { mesh->faces[i].material = 0; } for (i = 0; i < 2; ++i) { mesh->faces[8+i].material = 1; } for (i = 0; i < 2; ++i) { mesh->faces[10+i].material = 2; } inst = lib3ds_node_new_mesh_instance(mesh, "01", NULL, NULL, NULL); lib3ds_file_append_node(file, (Lib3dsNode*)inst, NULL); } { Lib3dsCamera *camera; Lib3dsCameraNode *n; Lib3dsTargetNode *t; int i; camera = lib3ds_camera_new("camera01"); lib3ds_file_insert_camera(file, camera, -1); lib3ds_vector_make(camera->position, 0.0, -100, 0.0); lib3ds_vector_make(camera->target, 0.0, 0.0, 0.0); n = lib3ds_node_new_camera(camera); t = lib3ds_node_new_camera_target(camera); lib3ds_file_append_node(file, (Lib3dsNode*)n, NULL); lib3ds_file_append_node(file, (Lib3dsNode*)t, NULL); lib3ds_track_resize(&n->pos_track, 37); for (i = 0; i <= 36; i++) { n->pos_track.keys[i].frame = 10 * i; lib3ds_vector_make(n->pos_track.keys[i].value, (float)(100.0 * cos(2 * M_PI * i / 36.0)), (float)(100.0 * sin(2 * M_PI * i / 36.0)), 50.0 ); } } if (!lib3ds_file_save(file, "cube.3ds")) { fprintf(stderr, "ERROR: Saving 3ds file failed!\n"); } lib3ds_file_free(file); }
// TODO: Build own exporter class void objectExporter::on_buttonBox_accepted() { QString fileName = QFileDialog::getSaveFileName(gloParent, "Save 3ds Object", ".", "3D Object (*.3ds)", 0, 0); QList<trackHandler*> trackList = gloParent->getTrackList(); trackHandler* curTrack = trackList[ui->trackBox->currentIndex()]; trackMesh* mesh = curTrack->mMesh; QVector<float> *vertices = new QVector<float>(); QVector<unsigned int> *indices = new QVector<unsigned int>(); QVector<unsigned int> *borders = new QVector<unsigned int>(); Lib3dsFile *file = lib3ds_file_new(); file->frames = 360; { Lib3dsMaterial* mat = lib3ds_material_new("coaster"); lib3ds_file_insert_material(file, mat, -1); mat->diffuse[0] = curTrack->trackColors[0].red()/255.f; mat->diffuse[1] = curTrack->trackColors[0].green()/255.f; mat->diffuse[2] = curTrack->trackColors[0].blue()/255.f; } { for(int section = 0; section < curTrack->trackData->lSections.size(); ++section) { vertices->clear(); indices->clear(); borders->clear(); mesh->build3ds(section, vertices, indices, borders); float* fvertices = new float[vertices->size()]; for(int i = 0; i < vertices->size()/3; ++i) { fvertices[3*i+0] = vertices->at(3*i+0); fvertices[3*i+1] = -vertices->at(3*i+2); fvertices[3*i+2] = vertices->at(3*i+1); //exportScreen->doFastExport(); } for(int subIndex = 0; subIndex < borders->size()-2; subIndex+= 2) { int fromVIndex = borders->at(subIndex)/3; int toVIndex = borders->at(subIndex+2)/3; int fromIIndex = borders->at(subIndex+1)/3; int toIIndex = borders->at(subIndex+3)/3; int i, j; QString name = QString::number(section).append(QString("_").append(QString::number(subIndex/2))); Lib3dsMesh *mesh = lib3ds_mesh_new(name.toLocal8Bit().data()); Lib3dsMeshInstanceNode *inst; lib3ds_file_insert_mesh(file, mesh, -1); lib3ds_mesh_resize_vertices(mesh, toVIndex-fromVIndex, 1, 0); for (i = 0; i < toVIndex-fromVIndex; ++i) { lib3ds_vector_copy(mesh->vertices[i], &fvertices[(i+fromVIndex)*3]); mesh->texcos[i][0] = 0.f; mesh->texcos[i][1] = 0.f; } lib3ds_mesh_resize_faces(mesh, toIIndex-fromIIndex); for (i = 0; i < toIIndex-fromIIndex; ++i) { for (j = 0; j < 3; ++j) { mesh->faces[i].index[j] = indices->at(3*(i+fromIIndex)+j)-fromVIndex; mesh->faces[i].material = 0; } } inst = lib3ds_node_new_mesh_instance(mesh, name.toLocal8Bit().data(), NULL, NULL, NULL); lib3ds_file_append_node(file, (Lib3dsNode*)inst, NULL); } delete[] fvertices; } } { Lib3dsCamera *camera; Lib3dsCameraNode *n; Lib3dsTargetNode *t; int i; camera = lib3ds_camera_new("camera01"); lib3ds_file_insert_camera(file, camera, -1); lib3ds_vector_make(camera->position, 0.0, -100, 0.0); lib3ds_vector_make(camera->target, 0.0, 0.0, 0.0); n = lib3ds_node_new_camera(camera); t = lib3ds_node_new_camera_target(camera); lib3ds_file_append_node(file, (Lib3dsNode*)n, NULL); lib3ds_file_append_node(file, (Lib3dsNode*)t, NULL); lib3ds_track_resize(&n->pos_track, 37); for (i = 0; i <= 36; i++) { n->pos_track.keys[i].frame = 10 * i; lib3ds_vector_make(n->pos_track.keys[i].value, (float)(100.0 * cos(2 * F_PI * i / 36.0)), (float)(100.0 * sin(2 * F_PI * i / 36.0)), 50.0 ); } } if (!lib3ds_file_save(file, fileName.toLocal8Bit().data())) { qDebug("ERROR: Saving 3ds file failed!\n"); } lib3ds_file_free(file); delete indices; delete vertices; }
void WriterNodeVisitor::buildFaces(osg::Geode & geo, const osg::Matrix & mat, ListTriangle & listTriangles, bool texcoords) { unsigned int nbTrianglesRemaining = listTriangles.size(); unsigned int nbVerticesRemaining = calcVertices(geo); // May set _succeded to false if (!succeeded()) return; std::string name( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), true, "geo") ); if (!succeeded()) return; Lib3dsMesh *mesh = lib3ds_mesh_new( name.c_str() ); if (!mesh) { OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl; _succeeded = false; return; } //copyOsgMatrixToLib3dsMatrix(mesh->matrix, mat); lib3ds_mesh_resize_faces (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining, MAX_VERTICES), texcoords ? 0 : 1, 0); // Not mandatory but will allocate once a big block // Test if the mesh will be split and needs sorting if (nbVerticesRemaining >= MAX_VERTICES || nbTrianglesRemaining >= MAX_FACES) { OSG_INFO << "Sorting elements..." << std::endl; WriterCompareTriangle cmp(geo, nbVerticesRemaining); std::sort(listTriangles.begin(), listTriangles.end(), cmp); } MapIndices index_vert; unsigned int numFace = 0; // Current face index for (ListTriangle::iterator it = listTriangles.begin(); it != listTriangles.end(); ++it) //Go through the triangle list to define meshs { // Test if the mesh will be full after adding a face if (index_vert.size()+3 >= MAX_VERTICES || numFace+1 >= MAX_FACES) { // Finnish mesh lib3ds_mesh_resize_faces (mesh, numFace); //lib3ds_mesh_resize_vertices() will be called in buildMesh() buildMesh(geo, mat, index_vert, texcoords, mesh); // May set _succeded to false if (!succeeded()) { lib3ds_mesh_free(mesh); return; } // "Reset" values and start over a new mesh index_vert.clear(); nbTrianglesRemaining -= numFace; numFace = 0; // We can't call a thing like "nbVerticesRemaining -= ...;" because points may be used multiple times. // [Sukender: An optimisation here would take too much time I think.] mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), true, "geo").c_str()); if (!mesh) { OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl; _succeeded = false; return; } lib3ds_mesh_resize_faces (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining, MAX_VERTICES), texcoords ? 0 : 1, 0); // Not mandatory but will allocate once a big block } Lib3dsFace & face = mesh->faces[numFace++]; face.index[0] = getMeshIndexForGeometryIndex(index_vert, it->first.t1, it->second); face.index[1] = getMeshIndexForGeometryIndex(index_vert, it->first.t2, it->second); face.index[2] = getMeshIndexForGeometryIndex(index_vert, it->first.t3, it->second); face.material = it->first.material; } buildMesh(geo, mat, index_vert, texcoords, mesh); // May set _succeded to false if (!succeeded()) { lib3ds_mesh_free(mesh); return; } }
void LD3dsExporter::doExport( LDLModel *pModel, Lib3dsNode *pParentNode, const TCFloat *matrix, int colorNumber, bool inPart, bool bfc, bool invert) { LDLFileLineArray *pFileLines = pModel->getFileLines(); if (pFileLines != NULL) { BFCState newBfcState = pModel->getBFCState(); int count = pModel->getActiveLineCount(); std::string meshName; Lib3dsMesh *pMesh = NULL; Lib3dsNode *pChildNode = NULL; // Lib3dsMeshInstanceNode *pInst; bool linesInvert = invert; bool isNew = false; if (TCVector::determinant(matrix) < 0.0f) { linesInvert = !linesInvert; } bfc = (bfc && newBfcState == BFCOnState) || newBfcState == BFCForcedOnState; meshName.resize(128); sprintf(&meshName[0], "m_%06d", ++m_meshCount); // meshName = getMeshName(pModel, pMesh); if (pMesh == NULL) { pMesh = lib3ds_mesh_new(meshName.c_str()); // memcpy(pMesh->matrix, matrix, sizeof(pMesh->matrix)); m_meshes[meshName] = pMesh; lib3ds_file_insert_mesh(m_file, pMesh, -1); isNew = true; } // pInst = lib3ds_node_new_mesh_instance(pMesh, // NULL/*(meshName + "n").c_str()*/, NULL, NULL, NULL); // pChildNode = (Lib3dsNode *)pInst; // memcpy(pChildNode->matrix, matrix, sizeof(float) * 16); // lib3ds_file_append_node(m_file, pChildNode, pParentNode); VertexVector vecVertices; FaceVector vecFaces; for (int i = 0; i < count; i++) { LDLFileLine *pFileLine = (*pFileLines)[i]; if (!pFileLine->isValid()) { continue; } switch (pFileLine->getLineType()) { case LDLLineTypeTriangle: case LDLLineTypeQuad: writeShapeLine(vecVertices, vecFaces, (LDLShapeLine *)pFileLine, matrix, colorNumber, bfc, linesInvert); break; case LDLLineTypeModel: { LDLModelLine *pModelLine = (LDLModelLine *)pFileLine; LDLModel *pOtherModel = pModelLine->getModel(true); if (pOtherModel != NULL) { TCFloat newMatrix[16]; int otherColorNumber = pModelLine->getColorNumber(); bool otherInPart = inPart; bool otherInvert = invert; if (pModelLine->getBFCInvert()) { otherInvert = !otherInvert; } if (otherColorNumber == 16) { otherColorNumber = colorNumber; } TCVector::multMatrix(matrix, pModelLine->getMatrix(), newMatrix); if (!inPart && pOtherModel->isPart() && m_seams) { TCVector min, max; TCFloat seamMatrix[16]; TCFloat tempMatrix[16]; pOtherModel->getBoundingBox(min, max); TCVector::calcScaleMatrix(m_seamWidth, seamMatrix, min, max); TCVector::multMatrix(newMatrix, seamMatrix, tempMatrix); memcpy(newMatrix, tempMatrix, sizeof(newMatrix)); otherInPart = true; } doExport(pOtherModel, pChildNode, newMatrix, otherColorNumber, otherInPart, bfc, otherInvert); } } break; default: // Get rid of warning break; } } if (isNew && vecVertices.size() > 0) { lib3ds_mesh_resize_vertices(pMesh, (int)vecVertices.size(), 0, 0); memcpy(pMesh->vertices, &vecVertices[0], sizeof(vecVertices[0]) * vecVertices.size()); lib3ds_mesh_resize_faces(pMesh, (int)vecFaces.size()); memcpy(pMesh->faces, &vecFaces[0], sizeof(vecFaces[0]) * vecFaces.size()); } else { --m_meshCount; } } }