diff --git a/common/lc_basewindow.h b/common/lc_basewindow.h index 1a161a01..0c7d21b1 100644 --- a/common/lc_basewindow.h +++ b/common/lc_basewindow.h @@ -100,7 +100,7 @@ struct lcPropertiesDialogOptions String Title; bool SetDefault; - lcArray PartsUsed; + lcArray PartsList; }; struct lcArrayDialogOptions diff --git a/common/lc_global.h b/common/lc_global.h index 847f0dce..31b5c795 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -16,6 +16,7 @@ class lcPiece; class lcCamera; class lcLight; class lcGroup; +class PieceInfo; class lcVector2; class lcVector3; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2793e42e..1b6b3d0f 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -8,6 +8,7 @@ #include "lc_profile.h" #include "lc_library.h" #include "lc_texture.h" +#include "pieceinf.h" #include "view.h" #include "preview.h" @@ -1103,6 +1104,37 @@ bool lcModel::GetPiecesBoundingBox(float BoundingBox[6]) const return true; } +void lcModel::GetPartsList(lcArray& PartsList) const +{ + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + + if (Piece->mPieceInfo->m_strDescription[0] == '~') + continue; + + int UsedIdx; + + for (UsedIdx = 0; UsedIdx < PartsList.GetSize(); UsedIdx++) + { + if (PartsList[UsedIdx].Info != Piece->mPieceInfo || PartsList[UsedIdx].ColorIndex != Piece->mColorIndex) + continue; + + PartsList[UsedIdx].Count++; + break; + } + + if (UsedIdx == PartsList.GetSize()) + { + lcPartsListEntry& Entry = PartsList.Add(); + + Entry.Info = Piece->mPieceInfo; + Entry.ColorIndex = Piece->mColorIndex; + Entry.Count = 1; + } + } +} + void lcModel::UpdateSelection() const { int Flags = 0; @@ -1616,3 +1648,980 @@ void lcModel::ZoomRegionToolClicked(lcCamera* Camera, const lcVector3* Points, f if (!Camera->IsSimple()) SaveCheckpoint(tr("Zoom")); } + +void lcModel::Export3DStudio() const +{ + if (mPieces.IsEmpty()) + { + gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); + return; + } + + char FileName[LC_MAXPATH]; + memset(FileName, 0, sizeof(FileName)); + + if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_3DSTUDIO, FileName)) + return; + + lcDiskFile File; + + if (!File.Open(FileName, "wb")) + { + gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); + return; + } + + long M3DStart = File.GetPosition(); + File.WriteU16(0x4D4D); // CHK_M3DMAGIC + File.WriteU32(0); + + File.WriteU16(0x0002); // CHK_M3D_VERSION + File.WriteU32(10); + File.WriteU32(3); + + long MDataStart = File.GetPosition(); + File.WriteU16(0x3D3D); // CHK_MDATA + File.WriteU32(0); + + File.WriteU16(0x3D3E); // CHK_MESH_VERSION + File.WriteU32(10); + File.WriteU32(3); + + const int MaterialNameLength = 11; + char MaterialName[32]; + + for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) + { + lcColor* Color = &gColorList[ColorIdx]; + + sprintf(MaterialName, "Material%03d", ColorIdx); + + long MaterialStart = File.GetPosition(); + File.WriteU16(0xAFFF); // CHK_MAT_ENTRY + File.WriteU32(0); + + File.WriteU16(0xA000); // CHK_MAT_NAME + File.WriteU32(6 + MaterialNameLength + 1); + File.WriteBuffer(MaterialName, MaterialNameLength + 1); + + File.WriteU16(0xA010); // CHK_MAT_AMBIENT + File.WriteU32(24); + + File.WriteU16(0x0011); // CHK_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); + + File.WriteU16(0x0012); // CHK_LIN_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); + + File.WriteU16(0xA020); // CHK_MAT_AMBIENT + File.WriteU32(24); + + File.WriteU16(0x0011); // CHK_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); + + File.WriteU16(0x0012); // CHK_LIN_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); + File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); + + File.WriteU16(0xA030); // CHK_MAT_SPECULAR + File.WriteU32(24); + + File.WriteU16(0x0011); // CHK_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + + File.WriteU16(0x0012); // CHK_LIN_COLOR_24 + File.WriteU32(9); + + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + File.WriteU8(floor(255.0 * 0.9f + 0.5)); + + File.WriteU16(0xA040); // CHK_MAT_SHININESS + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * 0.25 + 0.5)); + + File.WriteU16(0xA041); // CHK_MAT_SHIN2PCT + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * 0.05 + 0.5)); + + File.WriteU16(0xA050); // CHK_MAT_TRANSPARENCY + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * (1.0f - Color->Value[3]) + 0.5)); + + File.WriteU16(0xA052); // CHK_MAT_XPFALL + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5)); + + File.WriteU16(0xA053); // CHK_MAT_REFBLUR + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * 0.2 + 0.5)); + + File.WriteU16(0xA100); // CHK_MAT_SHADING + File.WriteU32(8); + + File.WriteS16(3); + + File.WriteU16(0xA084); // CHK_MAT_SELF_ILPCT + File.WriteU32(14); + + File.WriteU16(0x0030); // CHK_INT_PERCENTAGE + File.WriteU32(8); + + File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5)); + + File.WriteU16(0xA081); // CHK_MAT_TWO_SIDE + File.WriteU32(6); + + File.WriteU16(0xA087); // CHK_MAT_WIRE_SIZE + File.WriteU32(10); + + File.WriteFloat(1.0f); + + long MaterialEnd = File.GetPosition(); + File.Seek(MaterialStart + 2, SEEK_SET); + File.WriteU32(MaterialEnd - MaterialStart); + File.Seek(MaterialEnd, SEEK_SET); + } + + File.WriteU16(0x0100); // CHK_MASTER_SCALE + File.WriteU32(10); + + File.WriteFloat(1.0f); + + File.WriteU16(0x1400); // CHK_LO_SHADOW_BIAS + File.WriteU32(10); + + File.WriteFloat(1.0f); + + File.WriteU16(0x1420); // CHK_SHADOW_MAP_SIZE + File.WriteU32(8); + + File.WriteS16(512); + + File.WriteU16(0x1450); // CHK_SHADOW_FILTER + File.WriteU32(10); + + File.WriteFloat(3.0f); + + File.WriteU16(0x1460); // CHK_RAY_BIAS + File.WriteU32(10); + + File.WriteFloat(1.0f); + + File.WriteU16(0x1500); // CHK_O_CONSTS + File.WriteU32(18); + + File.WriteFloat(0.0f); + File.WriteFloat(0.0f); + File.WriteFloat(0.0f); + + File.WriteU16(0x2100); // CHK_AMBIENT_LIGHT + File.WriteU32(42); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mAmbientColor, 3); + + File.WriteU16(0x0013); // CHK_LIN_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mAmbientColor, 3); + + File.WriteU16(0x1200); // CHK_SOLID_BGND + File.WriteU32(42); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundSolidColor, 3); + + File.WriteU16(0x0013); // CHK_LIN_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundSolidColor, 3); + + File.WriteU16(0x1100); // CHK_BIT_MAP + QByteArray BackgroundImage = mProperties.mBackgroundImage.toLatin1(); + File.WriteU32(6 + 1 + strlen(BackgroundImage.constData())); + File.WriteBuffer(BackgroundImage.constData(), strlen(BackgroundImage.constData()) + 1); + + File.WriteU16(0x1300); // CHK_V_GRADIENT + File.WriteU32(118); + + File.WriteFloat(1.0f); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundGradientColor1, 3); + + File.WriteU16(0x0013); // CHK_LIN_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundGradientColor1, 3); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats((mProperties.mBackgroundGradientColor1 + mProperties.mBackgroundGradientColor2) / 2.0f, 3); + + File.WriteU16(0x0013); // CHK_LIN_COLOR_F + File.WriteU32(18); + + File.WriteFloats((mProperties.mBackgroundGradientColor1 + mProperties.mBackgroundGradientColor2) / 2.0f, 3); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundGradientColor2, 3); + + File.WriteU16(0x0013); // CHK_LIN_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mBackgroundGradientColor2, 3); + + if (mProperties.mBackgroundType == LC_BACKGROUND_GRADIENT) + { + File.WriteU16(0x1301); // LIB3DS_USE_V_GRADIENT + File.WriteU32(6); + } + else if (mProperties.mBackgroundType == LC_BACKGROUND_IMAGE) + { + File.WriteU16(0x1101); // LIB3DS_USE_BIT_MAP + File.WriteU32(6); + } + else + { + File.WriteU16(0x1201); // LIB3DS_USE_SOLID_BGND + File.WriteU32(6); + } + + File.WriteU16(0x2200); // CHK_FOG + File.WriteU32(46); + + File.WriteFloat(0.0f); + File.WriteFloat(0.0f); + File.WriteFloat(1000.0f); + File.WriteFloat(100.0f); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mFogColor, 3); + + File.WriteU16(0x2210); // CHK_FOG_BGND + File.WriteU32(6); + + File.WriteU16(0x2302); // CHK_LAYER_FOG + File.WriteU32(40); + + File.WriteFloat(0.0f); + File.WriteFloat(100.0f); + File.WriteFloat(50.0f); + File.WriteU32(0x00100000); + + File.WriteU16(0x0010); // CHK_COLOR_F + File.WriteU32(18); + + File.WriteFloats(mProperties.mFogColor, 3); + + File.WriteU16(0x2300); // CHK_DISTANCE_CUE + File.WriteU32(28); + + File.WriteFloat(0.0f); + File.WriteFloat(0.0f); + File.WriteFloat(1000.0f); + File.WriteFloat(100.0f); + + File.WriteU16(0x2310); // CHK_DICHK_DCUE_BGNDSTANCE_CUE + File.WriteU32(6); + + int NumPieces = 0; + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* piece = mPieces[PieceIdx]; + PieceInfo* Info = piece->mPieceInfo; + lcMesh* Mesh = Info->mMesh; + + if (Mesh->mIndexType == GL_UNSIGNED_INT) + continue; + + long NamedObjectStart = File.GetPosition(); + File.WriteU16(0x4000); // CHK_NAMED_OBJECT + File.WriteU32(0); + + char Name[32]; + sprintf(Name, "Piece%.3d", NumPieces); + NumPieces++; + File.WriteBuffer(Name, strlen(Name) + 1); + + long TriObjectStart = File.GetPosition(); + File.WriteU16(0x4100); // CHK_N_TRI_OBJECT + File.WriteU32(0); + + File.WriteU16(0x4110); // CHK_POINT_ARRAY + File.WriteU32(8 + 12 * Mesh->mNumVertices); + + File.WriteU16(Mesh->mNumVertices); + + float* Verts = (float*)Mesh->mVertexBuffer.mData; + const lcMatrix44& ModelWorld = piece->mModelWorld; + + for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++) + { + lcVector3 Pos(Verts[VertexIdx * 3], Verts[VertexIdx * 3 + 1], Verts[VertexIdx * 3 + 2]); + Pos = lcMul31(Pos, ModelWorld); + File.WriteFloat(Pos[0]); + File.WriteFloat(Pos[1]); + File.WriteFloat(Pos[2]); + } + + File.WriteU16(0x4160); // CHK_MESH_MATRIX + File.WriteU32(54); + + lcMatrix44 Matrix = lcMatrix44Identity(); + File.WriteFloats(Matrix[0], 3); + File.WriteFloats(Matrix[1], 3); + File.WriteFloats(Matrix[2], 3); + File.WriteFloats(Matrix[3], 3); + + File.WriteU16(0x4165); // CHK_MESH_COLOR + File.WriteU32(7); + + File.WriteU8(0); + + long FaceArrayStart = File.GetPosition(); + File.WriteU16(0x4120); // CHK_FACE_ARRAY + File.WriteU32(0); + + int NumTriangles = 0; + + for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) + { + lcMeshSection* Section = &Mesh->mSections[SectionIdx]; + + if (Section->PrimitiveType != GL_TRIANGLES) + continue; + + NumTriangles += Section->NumIndices / 3; + } + + File.WriteU16(NumTriangles); + + for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) + { + lcMeshSection* Section = &Mesh->mSections[SectionIdx]; + + if (Section->PrimitiveType != GL_TRIANGLES) + continue; + + lcuint16* Indices = (lcuint16*)Mesh->mIndexBuffer.mData + Section->IndexOffset / sizeof(lcuint16); + + for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3) + { + File.WriteU16(Indices[IndexIdx + 0]); + File.WriteU16(Indices[IndexIdx + 1]); + File.WriteU16(Indices[IndexIdx + 2]); + File.WriteU16(7); + } + } + + NumTriangles = 0; + + for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) + { + lcMeshSection* Section = &Mesh->mSections[SectionIdx]; + + if (Section->PrimitiveType != GL_TRIANGLES) + continue; + + int MaterialIndex = Section->ColorIndex == gDefaultColor ? piece->mColorIndex : Section->ColorIndex; + + File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP + File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3); + + sprintf(MaterialName, "Material%03d", MaterialIndex); + File.WriteBuffer(MaterialName, MaterialNameLength + 1); + + File.WriteU16(Section->NumIndices / 3); + + for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3) + File.WriteU16(NumTriangles++); + } + + long FaceArrayEnd = File.GetPosition(); + File.Seek(FaceArrayStart + 2, SEEK_SET); + File.WriteU32(FaceArrayEnd - FaceArrayStart); + File.Seek(FaceArrayEnd, SEEK_SET); + + long TriObjectEnd = File.GetPosition(); + File.Seek(TriObjectStart + 2, SEEK_SET); + File.WriteU32(TriObjectEnd - TriObjectStart); + File.Seek(TriObjectEnd, SEEK_SET); + + long NamedObjectEnd = File.GetPosition(); + File.Seek(NamedObjectStart + 2, SEEK_SET); + File.WriteU32(NamedObjectEnd - NamedObjectStart); + File.Seek(NamedObjectEnd, SEEK_SET); + } + + long MDataEnd = File.GetPosition(); + File.Seek(MDataStart + 2, SEEK_SET); + File.WriteU32(MDataEnd - MDataStart); + File.Seek(MDataEnd, SEEK_SET); + + long KFDataStart = File.GetPosition(); + File.WriteU16(0xB000); // CHK_KFDATA + File.WriteU32(0); + + File.WriteU16(0xB00A); // LIB3DS_KFHDR + File.WriteU32(6 + 2 + 1 + 4); + + File.WriteS16(5); + File.WriteU8(0); + File.WriteS32(100); + + long KFDataEnd = File.GetPosition(); + File.Seek(KFDataStart + 2, SEEK_SET); + File.WriteU32(KFDataEnd - KFDataStart); + File.Seek(KFDataEnd, SEEK_SET); + + long M3DEnd = File.GetPosition(); + File.Seek(M3DStart + 2, SEEK_SET); + File.WriteU32(M3DEnd - M3DStart); + File.Seek(M3DEnd, SEEK_SET); +} + +void lcModel::ExportBrickLink() const +{ + if (mPieces.IsEmpty()) + { + gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); + return; + } + + char FileName[LC_MAXPATH]; + memset(FileName, 0, sizeof(FileName)); + + if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_BRICKLINK, FileName)) + return; + + lcDiskFile BrickLinkFile; + char Line[1024]; + + if (!BrickLinkFile.Open(FileName, "wt")) + { + gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); + return; + } + + lcArray PartsList; + GetPartsList(PartsList); + + const char* OldLocale = setlocale(LC_NUMERIC, "C"); + BrickLinkFile.WriteLine("\n"); + + for (int PieceIdx = 0; PieceIdx < PartsList.GetSize(); PieceIdx++) + { + BrickLinkFile.WriteLine(" \n"); + BrickLinkFile.WriteLine(" P\n"); + + sprintf(Line, " %s\n", PartsList[PieceIdx].Info->m_strName); + BrickLinkFile.WriteLine(Line); + + int Count = PartsList[PieceIdx].Count; + if (Count > 1) + { + sprintf(Line, " %d\n", Count); + BrickLinkFile.WriteLine(Line); + } + + int Color = lcGetBrickLinkColor(PartsList[PieceIdx].ColorIndex); + if (Color) + { + sprintf(Line, " %d\n", Color); + BrickLinkFile.WriteLine(Line); + } + + BrickLinkFile.WriteLine(" \n"); + } + + BrickLinkFile.WriteLine("\n"); + + setlocale(LC_NUMERIC, OldLocale); +} + +void lcModel::ExportCSV() const +{ + if (mPieces.IsEmpty()) + { + gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); + return; + } + + char FileName[LC_MAXPATH]; + memset(FileName, 0, sizeof(FileName)); + + if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_CSV, FileName)) + return; + + lcDiskFile CSVFile; + char Line[1024]; + + if (!CSVFile.Open(FileName, "wt")) + { + gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); + return; + } + + lcArray PartsList; + GetPartsList(PartsList); + + const char* OldLocale = setlocale(LC_NUMERIC, "C"); + CSVFile.WriteLine("Part Name,Color,Quantity,Part ID,Color Code\n"); + + for (int PieceIdx = 0; PieceIdx < PartsList.GetSize(); PieceIdx++) + { + sprintf(Line, "\"%s\",\"%s\",%d,%s,%d\n", PartsList[PieceIdx].Info->m_strDescription, gColorList[PartsList[PieceIdx].ColorIndex].Name, + PartsList[PieceIdx].Count, PartsList[PieceIdx].Info->m_strName, gColorList[PartsList[PieceIdx].ColorIndex].Code); + CSVFile.WriteLine(Line); + } + + setlocale(LC_NUMERIC, OldLocale); +} + +void lcModel::ExportPOVRay() const +{ + lcPOVRayDialogOptions Options; + + memset(Options.FileName, 0, sizeof(Options.FileName)); + strcpy(Options.POVRayPath, lcGetProfileString(LC_PROFILE_POVRAY_PATH)); + strcpy(Options.LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH)); + Options.Render = lcGetProfileInt(LC_PROFILE_POVRAY_RENDER); + + if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_POVRAY, &Options)) + return; + + lcSetProfileString(LC_PROFILE_POVRAY_PATH, Options.POVRayPath); + lcSetProfileString(LC_PROFILE_POVRAY_LGEO_PATH, Options.LGEOPath); + lcSetProfileInt(LC_PROFILE_POVRAY_RENDER, Options.Render); + + lcDiskFile POVFile; + + if (!POVFile.Open(Options.FileName, "wt")) + { + gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR); + return; + } + + char Line[1024]; + + lcPiecesLibrary* Library = lcGetPiecesLibrary(); + char* PieceTable = new char[Library->mPieces.GetSize() * LC_PIECE_NAME_LEN]; + int* PieceFlags = new int[Library->mPieces.GetSize()]; + int NumColors = gColorList.GetSize(); + char* ColorTable = new char[NumColors * LC_MAX_COLOR_NAME]; + + memset(PieceTable, 0, Library->mPieces.GetSize() * LC_PIECE_NAME_LEN); + memset(PieceFlags, 0, Library->mPieces.GetSize() * sizeof(int)); + memset(ColorTable, 0, NumColors * LC_MAX_COLOR_NAME); + + enum + { + LGEO_PIECE_LGEO = 0x01, + LGEO_PIECE_AR = 0x02, + LGEO_PIECE_SLOPE = 0x04 + }; + + enum + { + LGEO_COLOR_SOLID = 0x01, + LGEO_COLOR_TRANSPARENT = 0x02, + LGEO_COLOR_CHROME = 0x04, + LGEO_COLOR_PEARL = 0x08, + LGEO_COLOR_METALLIC = 0x10, + LGEO_COLOR_RUBBER = 0x20, + LGEO_COLOR_GLITTER = 0x40 + }; + + char LGEOPath[LC_MAXPATH]; + strcpy(LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH)); + + if (LGEOPath[0]) + { + lcDiskFile TableFile, ColorFile; + char Filename[LC_MAXPATH]; + + int Length = strlen(LGEOPath); + + if ((LGEOPath[Length - 1] != '\\') && (LGEOPath[Length - 1] != '/')) + strcat(LGEOPath, "/"); + + strcpy(Filename, LGEOPath); + strcat(Filename, "lg_elements.lst"); + + if (!TableFile.Open(Filename, "rt")) + { + delete[] PieceTable; + delete[] PieceFlags; + gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR); + return; + } + + while (TableFile.ReadLine(Line, sizeof(Line))) + { + char Src[1024], Dst[1024], Flags[1024]; + + if (*Line == ';') + continue; + + if (sscanf(Line,"%s%s%s", Src, Dst, Flags) != 3) + continue; + + strupr(Src); + + PieceInfo* Info = Library->FindPiece(Src, false); + if (!Info) + continue; + + int Index = Library->mPieces.FindIndex(Info); + + if (strchr(Flags, 'L')) + { + PieceFlags[Index] |= LGEO_PIECE_LGEO; + sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lg_%s", Dst); + } + + if (strchr(Flags, 'A')) + { + PieceFlags[Index] |= LGEO_PIECE_AR; + sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "ar_%s", Dst); + } + + if (strchr(Flags, 'S')) + PieceFlags[Index] |= LGEO_PIECE_SLOPE; + } + + strcpy(Filename, LGEOPath); + strcat(Filename, "lg_colors.lst"); + + if (!ColorFile.Open(Filename, "rt")) + { + delete[] PieceTable; + delete[] PieceFlags; + gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR); + return; + } + + while (ColorFile.ReadLine(Line, sizeof(Line))) + { + char Name[1024], Flags[1024]; + int Code; + + if (*Line == ';') + continue; + + if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3) + continue; + + int Color = lcGetColorIndex(Code); + if (Color >= NumColors) + continue; + + strcpy(&ColorTable[Color * LC_MAX_COLOR_NAME], Name); + } + } + + const char* OldLocale = setlocale(LC_NUMERIC, "C"); + + if (LGEOPath[0]) + { + POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n"); + + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* piece = mPieces[PieceIdx]; + PieceInfo* Info = piece->mPieceInfo; + + for (int CheckIdx = 0; CheckIdx < mPieces.GetSize(); CheckIdx++) + { + if (mPieces[CheckIdx]->mPieceInfo != Info) + continue; + + if (CheckIdx != PieceIdx) + break; + + int Index = Library->mPieces.FindIndex(Info); + + if (PieceTable[Index * LC_PIECE_NAME_LEN]) + { + sprintf(Line, "#include \"%s.inc\"\n", PieceTable + Index * LC_PIECE_NAME_LEN); + POVFile.WriteLine(Line); + } + + break; + } + } + + POVFile.WriteLine("\n"); + } + else + POVFile.WriteLine("#include \"colors.inc\"\n\n"); + + for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) + { + lcColor* Color = &gColorList[ColorIdx]; + + if (lcIsColorTranslucent(ColorIdx)) + { + sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n", + Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); + } + else + { + sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n", + Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); + } + + POVFile.WriteLine(Line); + + if (!ColorTable[ColorIdx * LC_MAX_COLOR_NAME]) + sprintf(&ColorTable[ColorIdx * LC_MAX_COLOR_NAME], "lc_%s", Color->SafeName); + } + + POVFile.WriteLine("\n"); + + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + PieceInfo* Info = Piece->mPieceInfo; + int Index = Library->mPieces.FindIndex(Info); + + if (PieceTable[Index * LC_PIECE_NAME_LEN]) + continue; + + char Name[LC_PIECE_NAME_LEN]; + char* Ptr; + + strcpy(Name, Info->m_strName); + while ((Ptr = strchr(Name, '-'))) + *Ptr = '_'; + + sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lc_%s", Name); + + Info->mMesh->ExportPOVRay(POVFile, Name, ColorTable); + + POVFile.WriteLine("}\n\n"); + + sprintf(Line, "#declare lc_%s_clear = lc_%s\n\n", Name, Name); + POVFile.WriteLine(Line); + } + + lcCamera* Camera = gMainWindow->GetActiveView()->mCamera; + const lcVector3& Position = Camera->mPosition; + const lcVector3& Target = Camera->mTargetPosition; + const lcVector3& Up = Camera->mUpVector; + + sprintf(Line, "camera {\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f\n}\n\n", + Up[0], Up[1], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy); + POVFile.WriteLine(Line); + sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\nlight_source { <0, 0, 20> White shadowless }\n\n", + mProperties.mBackgroundSolidColor[0], mProperties.mBackgroundSolidColor[1], mProperties.mBackgroundSolidColor[2]); + POVFile.WriteLine(Line); + + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + int Index = Library->mPieces.FindIndex(Piece->mPieceInfo); + int Color; + + Color = Piece->mColorIndex; + const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : ""; + + const float* f = Piece->mModelWorld; + + if (PieceFlags[Index] & LGEO_PIECE_SLOPE) + { + sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n" + " object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n" + " matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", + PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], PieceTable + Index * LC_PIECE_NAME_LEN, &ColorTable[Color * LC_MAX_COLOR_NAME], + -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); + } + else + { + sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", + PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); + } + + POVFile.WriteLine(Line); + } + + delete[] PieceTable; + delete[] PieceFlags; + setlocale(LC_NUMERIC, OldLocale); + POVFile.Close(); + + if (Options.Render) + { + lcArray Arguments; + char Argument[LC_MAXPATH + 32]; + + sprintf(Argument, "+I%s", Options.FileName); + Arguments.Add(Argument); + + if (Options.LGEOPath[0]) + { + sprintf(Argument, "+L%slg/", Options.LGEOPath); + Arguments.Add(Argument); + sprintf(Argument, "+L%sar/", Options.LGEOPath); + Arguments.Add(Argument); + } + + sprintf(Argument, "+o%s", Options.FileName); + char* Slash1 = strrchr(Argument, '\\'); + char* Slash2 = strrchr(Argument, '/'); + if (Slash1 || Slash2) + { + if (Slash1 > Slash2) + *(Slash1 + 1) = 0; + else + *(Slash2 + 1) = 0; + + Arguments.Add(Argument); + } + + g_App->RunProcess(Options.POVRayPath, Arguments); + } +} + +void lcModel::ExportWavefront() const +{ + char FileName[LC_MAXPATH]; + memset(FileName, 0, sizeof(FileName)); + + if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_WAVEFRONT, FileName)) + return; + + lcDiskFile OBJFile; + char Line[1024]; + + if (!OBJFile.Open(FileName, "wt")) + { + gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR); + return; + } + + char buf[LC_MAXPATH], *ptr; + lcuint32 vert = 1; + + const char* OldLocale = setlocale(LC_NUMERIC, "C"); + + OBJFile.WriteLine("# Model exported from LeoCAD\n"); + + strcpy(buf, FileName); + ptr = strrchr(buf, '.'); + if (ptr) + *ptr = 0; + + strcat(buf, ".mtl"); + ptr = strrchr(buf, '\\'); + if (ptr) + ptr++; + else + { + ptr = strrchr(buf, '/'); + if (ptr) + ptr++; + else + ptr = buf; + } + + sprintf(Line, "#\n\nmtllib %s\n\n", ptr); + OBJFile.WriteLine(Line); + + FILE* mat = fopen(buf, "wt"); + fputs("# Colors used by LeoCAD\n# You need to add transparency values\n#\n\n", mat); + for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) + { + lcColor* Color = &gColorList[ColorIdx]; + fprintf(mat, "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); + } + fclose(mat); + + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + const lcMatrix44& ModelWorld = Piece->mModelWorld; + PieceInfo* pInfo = Piece->mPieceInfo; + float* Verts = (float*)pInfo->mMesh->mVertexBuffer.mData; + + for (int i = 0; i < pInfo->mMesh->mNumVertices * 3; i += 3) + { + lcVector3 Vertex = lcMul31(lcVector3(Verts[i], Verts[i+1], Verts[i+2]), ModelWorld); + sprintf(Line, "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]); + OBJFile.WriteLine(Line); + } + + OBJFile.WriteLine("#\n\n"); + } + + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + PieceInfo* Info = Piece->mPieceInfo; + + strcpy(buf, Piece->GetName()); + for (unsigned int i = 0; i < strlen(buf); i++) + if ((buf[i] == '#') || (buf[i] == ' ')) + buf[i] = '_'; + + sprintf(Line, "g %s\n", buf); + OBJFile.WriteLine(Line); + + Info->mMesh->ExportWavefrontIndices(OBJFile, Piece->mColorCode, vert); + vert += Info->mMesh->mNumVertices; + } + + setlocale(LC_NUMERIC, OldLocale); +} diff --git a/common/lc_model.h b/common/lc_model.h index 152579bd..036b8479 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -100,6 +100,13 @@ struct lcModelHistoryEntry QString Description; }; +struct lcPartsListEntry +{ + PieceInfo* Info; + int ColorIndex; + int Count; +}; + class lcModel { public: @@ -153,6 +160,7 @@ public: lcObject* GetFocusObject() const; bool GetSelectionCenter(lcVector3& Center) const; bool GetPiecesBoundingBox(float BoundingBox[6]) const; + void GetPartsList(lcArray& PartsList) const; void FocusOrDeselectObject(const lcObjectSection& ObjectSection); void ClearSelectionAndSetFocus(lcObject* Object, lcuint32 Section); @@ -190,6 +198,12 @@ public: void UpdateRollTool(lcCamera* Camera, float Mouse); void ZoomRegionToolClicked(lcCamera* Camera, const lcVector3* Points, float RatioX, float RatioY); + void Export3DStudio() const; + void ExportBrickLink() const; + void ExportCSV() const; + void ExportPOVRay() const; + void ExportWavefront() const; + protected: void DeleteModel(); void DeleteHistory(); @@ -222,7 +236,7 @@ protected: lcArray mUndoHistory; lcArray mRedoHistory; - Q_DECLARE_TR_FUNCTIONS(lcModel) + Q_DECLARE_TR_FUNCTIONS(lcModel); }; #endif // _LC_MODEL_H_ diff --git a/common/project.cpp b/common/project.cpp index ff9c8f0c..993e2e05 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -1290,37 +1290,6 @@ void Project::ZoomExtents(int FirstView, int LastView) gMainWindow->UpdateAllViews(); } -void Project::GetPiecesUsed(lcArray& PiecesUsed) const -{ - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - - if (Piece->mPieceInfo->m_strDescription[0] == '~') - continue; - - int UsedIdx; - - for (UsedIdx = 0; UsedIdx < PiecesUsed.GetSize(); UsedIdx++) - { - if (PiecesUsed[UsedIdx].Info != Piece->mPieceInfo || PiecesUsed[UsedIdx].ColorIndex != Piece->mColorIndex) - continue; - - PiecesUsed[UsedIdx].Count++; - break; - } - - if (UsedIdx == PiecesUsed.GetSize()) - { - lcPiecesUsedEntry& Entry = PiecesUsed.Add(); - - Entry.Info = Piece->mPieceInfo; - Entry.ColorIndex = Piece->mColorIndex; - Entry.Count = 1; - } - } -} - // Create a series of pictures void Project::CreateImages(Image* images, int width, int height, lcStep from, lcStep to, bool hilite) { @@ -1454,744 +1423,6 @@ void Project::CreateHTMLPieceList(FILE* f, lcStep Step, bool bImages, const char delete[] ColorsUsed; } -void Project::Export3DStudio() -{ - if (mPieces.IsEmpty()) - { - gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); - return; - } - - char FileName[LC_MAXPATH]; - memset(FileName, 0, sizeof(FileName)); - - if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_3DSTUDIO, FileName)) - return; - - lcDiskFile File; - - if (!File.Open(FileName, "wb")) - { - gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); - return; - } - - long M3DStart = File.GetPosition(); - File.WriteU16(0x4D4D); // CHK_M3DMAGIC - File.WriteU32(0); - - File.WriteU16(0x0002); // CHK_M3D_VERSION - File.WriteU32(10); - File.WriteU32(3); - - long MDataStart = File.GetPosition(); - File.WriteU16(0x3D3D); // CHK_MDATA - File.WriteU32(0); - - File.WriteU16(0x3D3E); // CHK_MESH_VERSION - File.WriteU32(10); - File.WriteU32(3); - - const int MaterialNameLength = 11; - char MaterialName[32]; - - for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) - { - lcColor* Color = &gColorList[ColorIdx]; - - sprintf(MaterialName, "Material%03d", ColorIdx); - - long MaterialStart = File.GetPosition(); - File.WriteU16(0xAFFF); // CHK_MAT_ENTRY - File.WriteU32(0); - - File.WriteU16(0xA000); // CHK_MAT_NAME - File.WriteU32(6 + MaterialNameLength + 1); - File.WriteBuffer(MaterialName, MaterialNameLength + 1); - - File.WriteU16(0xA010); // CHK_MAT_AMBIENT - File.WriteU32(24); - - File.WriteU16(0x0011); // CHK_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); - - File.WriteU16(0x0012); // CHK_LIN_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); - - File.WriteU16(0xA020); // CHK_MAT_AMBIENT - File.WriteU32(24); - - File.WriteU16(0x0011); // CHK_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); - - File.WriteU16(0x0012); // CHK_LIN_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * Color->Value[0] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[1] + 0.5)); - File.WriteU8(floor(255.0 * Color->Value[2] + 0.5)); - - File.WriteU16(0xA030); // CHK_MAT_SPECULAR - File.WriteU32(24); - - File.WriteU16(0x0011); // CHK_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - - File.WriteU16(0x0012); // CHK_LIN_COLOR_24 - File.WriteU32(9); - - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - File.WriteU8(floor(255.0 * 0.9f + 0.5)); - - File.WriteU16(0xA040); // CHK_MAT_SHININESS - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * 0.25 + 0.5)); - - File.WriteU16(0xA041); // CHK_MAT_SHIN2PCT - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * 0.05 + 0.5)); - - File.WriteU16(0xA050); // CHK_MAT_TRANSPARENCY - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * (1.0f - Color->Value[3]) + 0.5)); - - File.WriteU16(0xA052); // CHK_MAT_XPFALL - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5)); - - File.WriteU16(0xA053); // CHK_MAT_REFBLUR - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * 0.2 + 0.5)); - - File.WriteU16(0xA100); // CHK_MAT_SHADING - File.WriteU32(8); - - File.WriteS16(3); - - File.WriteU16(0xA084); // CHK_MAT_SELF_ILPCT - File.WriteU32(14); - - File.WriteU16(0x0030); // CHK_INT_PERCENTAGE - File.WriteU32(8); - - File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5)); - - File.WriteU16(0xA081); // CHK_MAT_TWO_SIDE - File.WriteU32(6); - - File.WriteU16(0xA087); // CHK_MAT_WIRE_SIZE - File.WriteU32(10); - - File.WriteFloat(1.0f); - - long MaterialEnd = File.GetPosition(); - File.Seek(MaterialStart + 2, SEEK_SET); - File.WriteU32(MaterialEnd - MaterialStart); - File.Seek(MaterialEnd, SEEK_SET); - } - - File.WriteU16(0x0100); // CHK_MASTER_SCALE - File.WriteU32(10); - - File.WriteFloat(1.0f); - - File.WriteU16(0x1400); // CHK_LO_SHADOW_BIAS - File.WriteU32(10); - - File.WriteFloat(1.0f); - - File.WriteU16(0x1420); // CHK_SHADOW_MAP_SIZE - File.WriteU32(8); - - File.WriteS16(512); - - File.WriteU16(0x1450); // CHK_SHADOW_FILTER - File.WriteU32(10); - - File.WriteFloat(3.0f); - - File.WriteU16(0x1460); // CHK_RAY_BIAS - File.WriteU32(10); - - File.WriteFloat(1.0f); - - File.WriteU16(0x1500); // CHK_O_CONSTS - File.WriteU32(18); - - File.WriteFloat(0.0f); - File.WriteFloat(0.0f); - File.WriteFloat(0.0f); - - File.WriteU16(0x2100); // CHK_AMBIENT_LIGHT - File.WriteU32(42); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mAmbientColor, 3); - - File.WriteU16(0x0013); // CHK_LIN_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mAmbientColor, 3); - - File.WriteU16(0x1200); // CHK_SOLID_BGND - File.WriteU32(42); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundSolidColor, 3); - - File.WriteU16(0x0013); // CHK_LIN_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundSolidColor, 3); - - File.WriteU16(0x1100); // CHK_BIT_MAP - QByteArray BackgroundImage = mProperties.mBackgroundImage.toLatin1(); - File.WriteU32(6 + 1 + strlen(BackgroundImage.constData())); - File.WriteBuffer(BackgroundImage.constData(), strlen(BackgroundImage.constData()) + 1); - - File.WriteU16(0x1300); // CHK_V_GRADIENT - File.WriteU32(118); - - File.WriteFloat(1.0f); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundGradientColor1, 3); - - File.WriteU16(0x0013); // CHK_LIN_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundGradientColor1, 3); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats((mProperties.mBackgroundGradientColor1 + mProperties.mBackgroundGradientColor2) / 2.0f, 3); - - File.WriteU16(0x0013); // CHK_LIN_COLOR_F - File.WriteU32(18); - - File.WriteFloats((mProperties.mBackgroundGradientColor1 + mProperties.mBackgroundGradientColor2) / 2.0f, 3); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundGradientColor2, 3); - - File.WriteU16(0x0013); // CHK_LIN_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mBackgroundGradientColor2, 3); - - if (mProperties.mBackgroundType == LC_BACKGROUND_GRADIENT) - { - File.WriteU16(0x1301); // LIB3DS_USE_V_GRADIENT - File.WriteU32(6); - } - else if (mProperties.mBackgroundType == LC_BACKGROUND_IMAGE) - { - File.WriteU16(0x1101); // LIB3DS_USE_BIT_MAP - File.WriteU32(6); - } - else - { - File.WriteU16(0x1201); // LIB3DS_USE_SOLID_BGND - File.WriteU32(6); - } - - File.WriteU16(0x2200); // CHK_FOG - File.WriteU32(46); - - File.WriteFloat(0.0f); - File.WriteFloat(0.0f); - File.WriteFloat(1000.0f); - File.WriteFloat(100.0f); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mFogColor, 3); - - File.WriteU16(0x2210); // CHK_FOG_BGND - File.WriteU32(6); - - File.WriteU16(0x2302); // CHK_LAYER_FOG - File.WriteU32(40); - - File.WriteFloat(0.0f); - File.WriteFloat(100.0f); - File.WriteFloat(50.0f); - File.WriteU32(0x00100000); - - File.WriteU16(0x0010); // CHK_COLOR_F - File.WriteU32(18); - - File.WriteFloats(mProperties.mFogColor, 3); - - File.WriteU16(0x2300); // CHK_DISTANCE_CUE - File.WriteU32(28); - - File.WriteFloat(0.0f); - File.WriteFloat(0.0f); - File.WriteFloat(1000.0f); - File.WriteFloat(100.0f); - - File.WriteU16(0x2310); // CHK_DICHK_DCUE_BGNDSTANCE_CUE - File.WriteU32(6); - - int NumPieces = 0; - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* piece = mPieces[PieceIdx]; - PieceInfo* Info = piece->mPieceInfo; - lcMesh* Mesh = Info->mMesh; - - if (Mesh->mIndexType == GL_UNSIGNED_INT) - continue; - - long NamedObjectStart = File.GetPosition(); - File.WriteU16(0x4000); // CHK_NAMED_OBJECT - File.WriteU32(0); - - char Name[32]; - sprintf(Name, "Piece%.3d", NumPieces); - NumPieces++; - File.WriteBuffer(Name, strlen(Name) + 1); - - long TriObjectStart = File.GetPosition(); - File.WriteU16(0x4100); // CHK_N_TRI_OBJECT - File.WriteU32(0); - - File.WriteU16(0x4110); // CHK_POINT_ARRAY - File.WriteU32(8 + 12 * Mesh->mNumVertices); - - File.WriteU16(Mesh->mNumVertices); - - float* Verts = (float*)Mesh->mVertexBuffer.mData; - const lcMatrix44& ModelWorld = piece->mModelWorld; - - for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++) - { - lcVector3 Pos(Verts[VertexIdx * 3], Verts[VertexIdx * 3 + 1], Verts[VertexIdx * 3 + 2]); - Pos = lcMul31(Pos, ModelWorld); - File.WriteFloat(Pos[0]); - File.WriteFloat(Pos[1]); - File.WriteFloat(Pos[2]); - } - - File.WriteU16(0x4160); // CHK_MESH_MATRIX - File.WriteU32(54); - - lcMatrix44 Matrix = lcMatrix44Identity(); - File.WriteFloats(Matrix[0], 3); - File.WriteFloats(Matrix[1], 3); - File.WriteFloats(Matrix[2], 3); - File.WriteFloats(Matrix[3], 3); - - File.WriteU16(0x4165); // CHK_MESH_COLOR - File.WriteU32(7); - - File.WriteU8(0); - - long FaceArrayStart = File.GetPosition(); - File.WriteU16(0x4120); // CHK_FACE_ARRAY - File.WriteU32(0); - - int NumTriangles = 0; - - for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) - { - lcMeshSection* Section = &Mesh->mSections[SectionIdx]; - - if (Section->PrimitiveType != GL_TRIANGLES) - continue; - - NumTriangles += Section->NumIndices / 3; - } - - File.WriteU16(NumTriangles); - - for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) - { - lcMeshSection* Section = &Mesh->mSections[SectionIdx]; - - if (Section->PrimitiveType != GL_TRIANGLES) - continue; - - lcuint16* Indices = (lcuint16*)Mesh->mIndexBuffer.mData + Section->IndexOffset / sizeof(lcuint16); - - for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3) - { - File.WriteU16(Indices[IndexIdx + 0]); - File.WriteU16(Indices[IndexIdx + 1]); - File.WriteU16(Indices[IndexIdx + 2]); - File.WriteU16(7); - } - } - - NumTriangles = 0; - - for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++) - { - lcMeshSection* Section = &Mesh->mSections[SectionIdx]; - - if (Section->PrimitiveType != GL_TRIANGLES) - continue; - - int MaterialIndex = Section->ColorIndex == gDefaultColor ? piece->mColorIndex : Section->ColorIndex; - - File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP - File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3); - - sprintf(MaterialName, "Material%03d", MaterialIndex); - File.WriteBuffer(MaterialName, MaterialNameLength + 1); - - File.WriteU16(Section->NumIndices / 3); - - for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3) - File.WriteU16(NumTriangles++); - } - - long FaceArrayEnd = File.GetPosition(); - File.Seek(FaceArrayStart + 2, SEEK_SET); - File.WriteU32(FaceArrayEnd - FaceArrayStart); - File.Seek(FaceArrayEnd, SEEK_SET); - - long TriObjectEnd = File.GetPosition(); - File.Seek(TriObjectStart + 2, SEEK_SET); - File.WriteU32(TriObjectEnd - TriObjectStart); - File.Seek(TriObjectEnd, SEEK_SET); - - long NamedObjectEnd = File.GetPosition(); - File.Seek(NamedObjectStart + 2, SEEK_SET); - File.WriteU32(NamedObjectEnd - NamedObjectStart); - File.Seek(NamedObjectEnd, SEEK_SET); - } - - long MDataEnd = File.GetPosition(); - File.Seek(MDataStart + 2, SEEK_SET); - File.WriteU32(MDataEnd - MDataStart); - File.Seek(MDataEnd, SEEK_SET); - - long KFDataStart = File.GetPosition(); - File.WriteU16(0xB000); // CHK_KFDATA - File.WriteU32(0); - - File.WriteU16(0xB00A); // LIB3DS_KFHDR - File.WriteU32(6 + 2 + 1 + 4); - - File.WriteS16(5); - File.WriteU8(0); - File.WriteS32(100); - - long KFDataEnd = File.GetPosition(); - File.Seek(KFDataStart + 2, SEEK_SET); - File.WriteU32(KFDataEnd - KFDataStart); - File.Seek(KFDataEnd, SEEK_SET); - - long M3DEnd = File.GetPosition(); - File.Seek(M3DStart + 2, SEEK_SET); - File.WriteU32(M3DEnd - M3DStart); - File.Seek(M3DEnd, SEEK_SET); -} - -void Project::ExportPOVRay(lcFile& POVFile) -{ - char Line[1024]; - - lcPiecesLibrary* Library = lcGetPiecesLibrary(); - char* PieceTable = new char[Library->mPieces.GetSize() * LC_PIECE_NAME_LEN]; - int* PieceFlags = new int[Library->mPieces.GetSize()]; - int NumColors = gColorList.GetSize(); - char* ColorTable = new char[NumColors * LC_MAX_COLOR_NAME]; - - memset(PieceTable, 0, Library->mPieces.GetSize() * LC_PIECE_NAME_LEN); - memset(PieceFlags, 0, Library->mPieces.GetSize() * sizeof(int)); - memset(ColorTable, 0, NumColors * LC_MAX_COLOR_NAME); - - enum - { - LGEO_PIECE_LGEO = 0x01, - LGEO_PIECE_AR = 0x02, - LGEO_PIECE_SLOPE = 0x04 - }; - - enum - { - LGEO_COLOR_SOLID = 0x01, - LGEO_COLOR_TRANSPARENT = 0x02, - LGEO_COLOR_CHROME = 0x04, - LGEO_COLOR_PEARL = 0x08, - LGEO_COLOR_METALLIC = 0x10, - LGEO_COLOR_RUBBER = 0x20, - LGEO_COLOR_GLITTER = 0x40 - }; - - char LGEOPath[LC_MAXPATH]; - strcpy(LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH)); - - // Parse LGEO tables. - if (LGEOPath[0]) - { - lcDiskFile TableFile, ColorFile; - char Filename[LC_MAXPATH]; - - int Length = strlen(LGEOPath); - - if ((LGEOPath[Length - 1] != '\\') && (LGEOPath[Length - 1] != '/')) - strcat(LGEOPath, "/"); - - strcpy(Filename, LGEOPath); - strcat(Filename, "lg_elements.lst"); - - if (!TableFile.Open(Filename, "rt")) - { - delete[] PieceTable; - delete[] PieceFlags; - gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR); - return; - } - - while (TableFile.ReadLine(Line, sizeof(Line))) - { - char Src[1024], Dst[1024], Flags[1024]; - - if (*Line == ';') - continue; - - if (sscanf(Line,"%s%s%s", Src, Dst, Flags) != 3) - continue; - - strupr(Src); - - PieceInfo* Info = Library->FindPiece(Src, false); - if (!Info) - continue; - - int Index = Library->mPieces.FindIndex(Info); - - if (strchr(Flags, 'L')) - { - PieceFlags[Index] |= LGEO_PIECE_LGEO; - sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lg_%s", Dst); - } - - if (strchr(Flags, 'A')) - { - PieceFlags[Index] |= LGEO_PIECE_AR; - sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "ar_%s", Dst); - } - - if (strchr(Flags, 'S')) - PieceFlags[Index] |= LGEO_PIECE_SLOPE; - } - - strcpy(Filename, LGEOPath); - strcat(Filename, "lg_colors.lst"); - - if (!ColorFile.Open(Filename, "rt")) - { - delete[] PieceTable; - delete[] PieceFlags; - gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR); - return; - } - - while (ColorFile.ReadLine(Line, sizeof(Line))) - { - char Name[1024], Flags[1024]; - int Code; - - if (*Line == ';') - continue; - - if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3) - continue; - - int Color = lcGetColorIndex(Code); - if (Color >= NumColors) - continue; - - strcpy(&ColorTable[Color * LC_MAX_COLOR_NAME], Name); - } - } - - const char* OldLocale = setlocale(LC_NUMERIC, "C"); - - // Add includes. - if (LGEOPath[0]) - { - POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n"); - - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* piece = mPieces[PieceIdx]; - PieceInfo* Info = piece->mPieceInfo; - - for (int CheckIdx = 0; CheckIdx < mPieces.GetSize(); CheckIdx++) - { - if (mPieces[CheckIdx]->mPieceInfo != Info) - continue; - - if (CheckIdx != PieceIdx) - break; - - int Index = Library->mPieces.FindIndex(Info); - - if (PieceTable[Index * LC_PIECE_NAME_LEN]) - { - sprintf(Line, "#include \"%s.inc\"\n", PieceTable + Index * LC_PIECE_NAME_LEN); - POVFile.WriteLine(Line); - } - - break; - } - } - - POVFile.WriteLine("\n"); - } - else - POVFile.WriteLine("#include \"colors.inc\"\n\n"); - - // Add color definitions. - for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) - { - lcColor* Color = &gColorList[ColorIdx]; - - if (lcIsColorTranslucent(ColorIdx)) - { - sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n", - Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); - } - else - { - sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n", - Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); - } - - POVFile.WriteLine(Line); - - if (!ColorTable[ColorIdx * LC_MAX_COLOR_NAME]) - sprintf(&ColorTable[ColorIdx * LC_MAX_COLOR_NAME], "lc_%s", Color->SafeName); - } - - POVFile.WriteLine("\n"); - - // Add pieces not included in LGEO. - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - PieceInfo* Info = Piece->mPieceInfo; - int Index = Library->mPieces.FindIndex(Info); - - if (PieceTable[Index * LC_PIECE_NAME_LEN]) - continue; - - char Name[LC_PIECE_NAME_LEN]; - char* Ptr; - - strcpy(Name, Info->m_strName); - while ((Ptr = strchr(Name, '-'))) - *Ptr = '_'; - - sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lc_%s", Name); - - Info->mMesh->ExportPOVRay(POVFile, Name, ColorTable); - - POVFile.WriteLine("}\n\n"); - - sprintf(Line, "#declare lc_%s_clear = lc_%s\n\n", Name, Name); - POVFile.WriteLine(Line); - } - - lcCamera* Camera = gMainWindow->GetActiveView()->mCamera; - const lcVector3& Position = Camera->mPosition; - const lcVector3& Target = Camera->mTargetPosition; - const lcVector3& Up = Camera->mUpVector; - - sprintf(Line, "camera {\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f\n}\n\n", - Up[0], Up[1], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy); - POVFile.WriteLine(Line); - sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\nlight_source { <0, 0, 20> White shadowless }\n\n", - mProperties.mBackgroundSolidColor[0], mProperties.mBackgroundSolidColor[1], mProperties.mBackgroundSolidColor[2]); - POVFile.WriteLine(Line); - - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - int Index = Library->mPieces.FindIndex(Piece->mPieceInfo); - int Color; - - Color = Piece->mColorIndex; - const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : ""; - - const float* f = Piece->mModelWorld; - - if (PieceFlags[Index] & LGEO_PIECE_SLOPE) - { - sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n" - " object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n" - " matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", - PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], PieceTable + Index * LC_PIECE_NAME_LEN, &ColorTable[Color * LC_MAX_COLOR_NAME], - -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); - } - else - { - sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", - PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); - } - - POVFile.WriteLine(Line); - } - - delete[] PieceTable; - delete[] PieceFlags; - setlocale(LC_NUMERIC, OldLocale); - POVFile.Close(); -} - void Project::HandleCommand(LC_COMMANDS id) { switch (id) @@ -2642,271 +1873,21 @@ void Project::HandleCommand(LC_COMMANDS id) } } break; - case LC_FILE_EXPORT_BRICKLINK: - { - if (mPieces.IsEmpty()) - { - gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); - break; - } + case LC_FILE_EXPORT_BRICKLINK: + ExportBrickLink(); + break; - char FileName[LC_MAXPATH]; - memset(FileName, 0, sizeof(FileName)); + case LC_FILE_EXPORT_CSV: + ExportCSV(); + break; - if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_BRICKLINK, FileName)) - break; + case LC_FILE_EXPORT_POVRAY: + ExportPOVRay(); + break; - lcDiskFile BrickLinkFile; - char Line[1024]; - - if (!BrickLinkFile.Open(FileName, "wt")) - { - gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); - break; - } - - lcArray PiecesUsed; - GetPiecesUsed(PiecesUsed); - - const char* OldLocale = setlocale(LC_NUMERIC, "C"); - BrickLinkFile.WriteLine("\n"); - - for (int PieceIdx = 0; PieceIdx < PiecesUsed.GetSize(); PieceIdx++) - { - BrickLinkFile.WriteLine(" \n"); - BrickLinkFile.WriteLine(" P\n"); - - sprintf(Line, " %s\n", PiecesUsed[PieceIdx].Info->m_strName); - BrickLinkFile.WriteLine(Line); - - int Count = PiecesUsed[PieceIdx].Count; - if (Count > 1) - { - sprintf(Line, " %d\n", Count); - BrickLinkFile.WriteLine(Line); - } - - int Color = lcGetBrickLinkColor(PiecesUsed[PieceIdx].ColorIndex); - if (Color) - { - sprintf(Line, " %d\n", Color); - BrickLinkFile.WriteLine(Line); - } - - BrickLinkFile.WriteLine(" \n"); - } - - BrickLinkFile.WriteLine("\n"); - - setlocale(LC_NUMERIC, OldLocale); - } break; - - case LC_FILE_EXPORT_CSV: - { - if (mPieces.IsEmpty()) - { - gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION); - break; - } - - char FileName[LC_MAXPATH]; - memset(FileName, 0, sizeof(FileName)); - - if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_CSV, FileName)) - break; - - lcDiskFile CSVFile; - char Line[1024]; - - if (!CSVFile.Open(FileName, "wt")) - { - gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR); - break; - } - - lcArray PiecesUsed; - GetPiecesUsed(PiecesUsed); - - const char* OldLocale = setlocale(LC_NUMERIC, "C"); - CSVFile.WriteLine("Part Name,Color,Quantity,Part ID,Color Code\n"); - - for (int PieceIdx = 0; PieceIdx < PiecesUsed.GetSize(); PieceIdx++) - { - sprintf(Line, "\"%s\",\"%s\",%d,%s,%d\n", PiecesUsed[PieceIdx].Info->m_strDescription, gColorList[PiecesUsed[PieceIdx].ColorIndex].Name, - PiecesUsed[PieceIdx].Count, PiecesUsed[PieceIdx].Info->m_strName, gColorList[PiecesUsed[PieceIdx].ColorIndex].Code); - CSVFile.WriteLine(Line); - } - - setlocale(LC_NUMERIC, OldLocale); - } break; - - case LC_FILE_EXPORT_POVRAY: - { - lcPOVRayDialogOptions Options; - - memset(Options.FileName, 0, sizeof(Options.FileName)); - strcpy(Options.POVRayPath, lcGetProfileString(LC_PROFILE_POVRAY_PATH)); - strcpy(Options.LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH)); - Options.Render = lcGetProfileInt(LC_PROFILE_POVRAY_RENDER); - - if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_POVRAY, &Options)) - break; - - lcSetProfileString(LC_PROFILE_POVRAY_PATH, Options.POVRayPath); - lcSetProfileString(LC_PROFILE_POVRAY_LGEO_PATH, Options.LGEOPath); - lcSetProfileInt(LC_PROFILE_POVRAY_RENDER, Options.Render); - - lcDiskFile POVFile; - - if (!POVFile.Open(Options.FileName, "wt")) - { - gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR); - break; - } - - ExportPOVRay(POVFile); - - if (Options.Render) - { - lcArray Arguments; - char Argument[LC_MAXPATH + 32]; - - sprintf(Argument, "+I%s", Options.FileName); - Arguments.Add(Argument); - - if (Options.LGEOPath[0]) - { - sprintf(Argument, "+L%slg/", Options.LGEOPath); - Arguments.Add(Argument); - sprintf(Argument, "+L%sar/", Options.LGEOPath); - Arguments.Add(Argument); - } - - sprintf(Argument, "+o%s", Options.FileName); - char* Slash1 = strrchr(Argument, '\\'); - char* Slash2 = strrchr(Argument, '/'); - if (Slash1 || Slash2) - { - if (Slash1 > Slash2) - *(Slash1 + 1) = 0; - else - *(Slash2 + 1) = 0; - - Arguments.Add(Argument); - } - - g_App->RunProcess(Options.POVRayPath, Arguments); - } - } break; - - case LC_FILE_EXPORT_WAVEFRONT: - { - char FileName[LC_MAXPATH]; - memset(FileName, 0, sizeof(FileName)); - - if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_WAVEFRONT, FileName)) - break; - - lcDiskFile OBJFile; - char Line[1024]; - - if (!OBJFile.Open(FileName, "wt")) - { - gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR); - break; - } - - char buf[LC_MAXPATH], *ptr; - lcuint32 vert = 1; - - const char* OldLocale = setlocale(LC_NUMERIC, "C"); - strcpy(buf, m_strPathName); - ptr = strrchr(buf, '\\'); - if (ptr) - ptr++; - else - { - ptr = strrchr(buf, '/'); - if (ptr) - ptr++; - else - ptr = buf; - } - - OBJFile.WriteLine("# Model exported from LeoCAD\n"); - - if (strlen(buf) != 0) - { - sprintf(Line, "# Original name: %s\n", ptr); - OBJFile.WriteLine(Line); - } - - strcpy(buf, FileName); - ptr = strrchr(buf, '.'); - if (ptr) - *ptr = 0; - - strcat(buf, ".mtl"); - ptr = strrchr(buf, '\\'); - if (ptr) - ptr++; - else - { - ptr = strrchr(buf, '/'); - if (ptr) - ptr++; - else - ptr = buf; - } - - sprintf(Line, "#\n\nmtllib %s\n\n", ptr); - OBJFile.WriteLine(Line); - - FILE* mat = fopen(buf, "wt"); - fputs("# Colors used by LeoCAD\n# You need to add transparency values\n#\n\n", mat); - for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++) - { - lcColor* Color = &gColorList[ColorIdx]; - fprintf(mat, "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); - } - fclose(mat); - - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - const lcMatrix44& ModelWorld = Piece->mModelWorld; - PieceInfo* pInfo = Piece->mPieceInfo; - float* Verts = (float*)pInfo->mMesh->mVertexBuffer.mData; - - for (int i = 0; i < pInfo->mMesh->mNumVertices * 3; i += 3) - { - lcVector3 Vertex = lcMul31(lcVector3(Verts[i], Verts[i+1], Verts[i+2]), ModelWorld); - sprintf(Line, "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]); - OBJFile.WriteLine(Line); - } - - OBJFile.WriteLine("#\n\n"); - } - - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - PieceInfo* Info = Piece->mPieceInfo; - - strcpy(buf, Piece->GetName()); - for (unsigned int i = 0; i < strlen(buf); i++) - if ((buf[i] == '#') || (buf[i] == ' ')) - buf[i] = '_'; - - sprintf(Line, "g %s\n", buf); - OBJFile.WriteLine(Line); - - Info->mMesh->ExportWavefrontIndices(OBJFile, Piece->mColorCode, vert); - vert += Info->mMesh->mNumVertices; - } - - setlocale(LC_NUMERIC, OldLocale); - } break; + case LC_FILE_EXPORT_WAVEFRONT: + ExportWavefront(); + break; case LC_FILE_PROPERTIES: { @@ -2916,7 +1897,7 @@ void Project::HandleCommand(LC_COMMANDS id) Options.Title = m_strTitle; Options.SetDefault = false; - GetPiecesUsed(Options.PartsUsed); + GetPartsList(Options.PartsList); if (!gMainWindow->DoDialog(LC_DIALOG_PROPERTIES, &Options)) break; diff --git a/common/project.h b/common/project.h index bdcfb526..199ffb68 100644 --- a/common/project.h +++ b/common/project.h @@ -41,13 +41,6 @@ struct LC_FILEENTRY char FileName[LC_MAXPATH]; }; -struct lcPiecesUsedEntry -{ - PieceInfo* Info; - int ColorIndex; - int Count; -}; - enum lcObjectProperty { LC_PIECE_PROPERTY_POSITION, @@ -96,7 +89,6 @@ public: public: void LoadDefaults(); - void GetPiecesUsed(lcArray& PiecesUsed) const; void CreateImages(Image* images, int width, int height, lcStep from, lcStep to, bool hilite); void Render(View* view, bool bToMemory); lcGroup* AddGroup(lcGroup* Parent); @@ -118,8 +110,6 @@ protected: void RenderSceneObjects(View* view); void CreateHTMLPieceList(FILE* f, lcStep Step, bool bImages, const char* ext); - void Export3DStudio(); - void ExportPOVRay(lcFile& File); void ZoomExtents(int FirstView, int LastView); bool DoSave(const char* FileName); diff --git a/qt/lc_qpropertiesdialog.cpp b/qt/lc_qpropertiesdialog.cpp index abb8a74b..cc6629c6 100644 --- a/qt/lc_qpropertiesdialog.cpp +++ b/qt/lc_qpropertiesdialog.cpp @@ -55,7 +55,7 @@ lcQPropertiesDialog::lcQPropertiesDialog(QWidget *parent, void *data) : ui->ambientColorButton->setIcon(pix); lcPiecesLibrary *library = lcGetPiecesLibrary(); - lcArray& partsUsed = options->PartsUsed; + lcArray& partsUsed = options->PartsList; QStringList horizontalLabels, partNames; bool *colorsUsed = new bool[gNumUserColors];