From 1cd4a8cee05259a0c073d057ea9a23c2f1866bdf Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 29 Feb 2016 20:13:54 +0000 Subject: [PATCH] Added support for flexible technic ribbed hoses. --- common/lc_library.cpp | 61 +++++++----- common/lc_library.h | 4 +- common/lc_mesh.cpp | 15 ++- common/lc_mesh.h | 4 +- common/lc_model.cpp | 6 +- common/lc_synth.cpp | 226 ++++++++++++++++++++++++++++++++++++++++++ common/lc_synth.h | 26 +++++ common/piece.cpp | 197 ++++++++++++++++++------------------ common/piece.h | 44 +++++--- common/pieceinf.cpp | 39 ++++---- common/pieceinf.h | 15 ++- leocad.pro | 2 + 12 files changed, 472 insertions(+), 167 deletions(-) create mode 100644 common/lc_synth.cpp create mode 100644 common/lc_synth.h diff --git a/common/lc_library.cpp b/common/lc_library.cpp index dc99d64e..b185dd72 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -10,6 +10,7 @@ #include "lc_mainwindow.h" #include "lc_context.h" #include "lc_glextensions.h" +#include "lc_synth.h" #include "project.h" #include #include @@ -181,6 +182,7 @@ bool lcPiecesLibrary::Load(const char* LibraryPath) } lcLoadDefaultCategories(); + lcSynthInit(); return true; } @@ -883,7 +885,7 @@ bool lcPiecesLibrary::LoadPiece(PieceInfo* Info) return false; const char* OldLocale = setlocale(LC_NUMERIC, "C"); - bool Ret = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED); + bool Ret = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED, true); setlocale(LC_NUMERIC, OldLocale); if (!Ret) @@ -904,7 +906,7 @@ bool lcPiecesLibrary::LoadPiece(PieceInfo* Info) return false; const char* OldLocale = setlocale(LC_NUMERIC, "C"); - bool Ret = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED); + bool Ret = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED, true); setlocale(LC_NUMERIC, OldLocale); if (!Ret) @@ -919,7 +921,7 @@ bool lcPiecesLibrary::LoadPiece(PieceInfo* Info) return true; } -void lcPiecesLibrary::CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData) +lcMesh* lcPiecesLibrary::CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData) { lcMesh* Mesh = new lcMesh(); @@ -1121,20 +1123,23 @@ void lcPiecesLibrary::CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData) } } - if (DstSection.PrimitiveType == GL_TRIANGLES) + if (Info) { - if (DstSection.ColorIndex == gDefaultColor) - Info->mFlags |= LC_PIECE_HAS_DEFAULT; - else + if (DstSection.PrimitiveType == GL_TRIANGLES) { - if (lcIsColorTranslucent(DstSection.ColorIndex)) - Info->mFlags |= LC_PIECE_HAS_TRANSLUCENT; + if (DstSection.ColorIndex == gDefaultColor) + Info->mFlags |= LC_PIECE_HAS_DEFAULT; else - Info->mFlags |= LC_PIECE_HAS_SOLID; + { + if (lcIsColorTranslucent(DstSection.ColorIndex)) + Info->mFlags |= LC_PIECE_HAS_TRANSLUCENT; + else + Info->mFlags |= LC_PIECE_HAS_SOLID; + } } + else + Info->mFlags |= LC_PIECE_HAS_LINES; } - else - Info->mFlags |= LC_PIECE_HAS_LINES; NumIndices += DstSection.NumIndices; } @@ -1190,7 +1195,11 @@ void lcPiecesLibrary::CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData) NumIndices += DstSection.NumIndices; } */ - Info->SetMesh(Mesh); + + if (Info) + Info->SetMesh(Mesh); + + return Mesh; } void lcPiecesLibrary::UpdateBuffers(lcContext* Context) @@ -1322,12 +1331,12 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) if (LowPrimitiveIndex == -1) { - if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED)) + if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true)) return false; } else { - if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_HIGH)) + if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_HIGH, true)) return false; lcLibraryPrimitive* LowPrimitive = mPrimitives[LowPrimitiveIndex]; @@ -1337,7 +1346,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) TextureStack.RemoveAll(); - if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_LOW)) + if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_LOW, true)) return false; } } @@ -1358,7 +1367,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) if (!PrimFile.Open(FileName, "rt")) return false; - if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED)) + if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true)) return false; } @@ -1367,7 +1376,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) return true; } -bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType) +bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize) { char Buffer[1024]; char* Line; @@ -1573,7 +1582,12 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf if (Primitive->mStud) MeshData.AddMeshDataNoDuplicateCheck(Primitive->mMeshData, IncludeTransform, ColorCode, TextureMap, MeshDataType); else if (!Primitive->mSubFile) - MeshData.AddMeshData(Primitive->mMeshData, IncludeTransform, ColorCode, TextureMap, MeshDataType); + { + if (Optimize) + MeshData.AddMeshData(Primitive->mMeshData, IncludeTransform, ColorCode, TextureMap, MeshDataType); + else + MeshData.AddMeshDataNoDuplicateCheck(Primitive->mMeshData, IncludeTransform, ColorCode, TextureMap, MeshDataType); + } else { if (mZipFiles[LC_ZIPFILE_OFFICIAL]) @@ -1583,7 +1597,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf if (!mZipFiles[Primitive->mZipFileType]->ExtractFile(Primitive->mZipFileIndex, IncludeFile)) continue; - if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType)) + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType, Optimize)) continue; } else @@ -1602,7 +1616,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf if (!IncludeFile.Open(FileName, "rt")) continue; - if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType)) + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType, Optimize)) continue; } } @@ -1623,7 +1637,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf if (!mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, IncludeFile)) break; - if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType)) + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType, Optimize)) break; } else @@ -1639,7 +1653,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf if (!IncludeFile.Open(FileName, "rt")) break; - if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType)) + if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, TextureStack, MeshData, MeshDataType, Optimize)) break; } @@ -2388,6 +2402,7 @@ bool lcPiecesLibrary::LoadBuiltinPieces() lcLoadDefaultColors(); lcLoadDefaultCategories(true); + lcSynthInit(); return true; } diff --git a/common/lc_library.h b/common/lc_library.h index 9924c61e..a1aefa98 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -155,8 +155,8 @@ public: mNumOfficialPieces = mPieces.GetSize(); } - bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType); - void CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData); + bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize); + lcMesh* CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData); void UpdateBuffers(lcContext* Context); void UnloadUnusedParts(); diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index 665e49fe..864fa259 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -133,10 +133,15 @@ void lcMesh::CreateBox() } template -bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& Intersection) +bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) { + float Distance; + if (!lcBoundingBoxRayIntersectDistance(mBoundingBox.Min, mBoundingBox.Max, Start, End, &Distance, NULL) || (Distance >= MinDistance)) + return false; + float* Verts = (float*)mVertexData; bool Hit = false; + lcVector3 Intersection; for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++) { @@ -156,7 +161,7 @@ bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, floa lcVector3 v2(p2[0], p2[1], p2[2]); lcVector3 v3(p3[0], p3[1], p3[2]); - if (lcLineTriangleMinIntersection(v1, v2, v3, Start, End, &MinDist, &Intersection)) + if (lcLineTriangleMinIntersection(v1, v2, v3, Start, End, &MinDistance, &Intersection)) Hit = true; } } @@ -164,12 +169,12 @@ bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, floa return Hit; } -bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& Intersection) +bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist) { if (mIndexType == GL_UNSIGNED_SHORT) - return MinIntersectDist(Start, End, MinDist, Intersection); + return MinIntersectDist(Start, End, MinDist); else - return MinIntersectDist(Start, End, MinDist, Intersection); + return MinIntersectDist(Start, End, MinDist); } template diff --git a/common/lc_mesh.h b/common/lc_mesh.h index 923ab6d5..0091b4f6 100644 --- a/common/lc_mesh.h +++ b/common/lc_mesh.h @@ -61,8 +61,8 @@ public: void ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int VertexOffset); template - bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& Intersection); - bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& Intersection); + bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist); + bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist); template bool IntersectsPlanes(const lcVector4 Planes[6]); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index e855f502..bd4a9330 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1200,7 +1200,11 @@ bool lcModel::SubModelMinIntersectDist(const lcVector3& WorldStart, const lcVect { lcPiece* Piece = mPieces[PieceIdx]; - if (Piece->GetStepHide() == LC_STEP_MAX && Piece->mPieceInfo->MinIntersectDist(Piece->mModelWorld, WorldStart, WorldEnd, MinDistance)) + lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(Piece->mModelWorld); + lcVector3 Start = lcMul31(WorldStart, InverseWorldMatrix); + lcVector3 End = lcMul31(WorldEnd, InverseWorldMatrix); + + if (Piece->GetStepHide() == LC_STEP_MAX && Piece->mPieceInfo->MinIntersectDist(Start, End, MinDistance)) // todo: this should check for piece->mMesh first MinIntersect = true; } diff --git a/common/lc_synth.cpp b/common/lc_synth.cpp new file mode 100644 index 00000000..eb8565aa --- /dev/null +++ b/common/lc_synth.cpp @@ -0,0 +1,226 @@ +#include "lc_global.h" +#include "lc_synth.h" +#include "lc_library.h" +#include "lc_application.h" +#include "pieceinf.h" + +void lcSynthInit() +{ + lcPiecesLibrary* Library = lcGetPiecesLibrary(); + + struct lcRibbedHoseInfo + { + const char* PartID; + float Length; + int NumSections; + }; + + lcRibbedHoseInfo RibbedHoseInfo[] = + { + { "72504", 15.625f, 4 }, // Technic Ribbed Hose 2L + { "72706", 25.0f, 7 }, // Technic Ribbed Hose 3L + { "71952", 37.5f, 11 }, // Technic Ribbed Hose 4L + { "71944", 56.25f, 17 }, // Technic Ribbed Hose 6L + { "71951", 71.875, 22 }, // Technic Ribbed Hose 8L + { "71986", 106.25f, 33 }, // Technic Ribbed Hose 11L + { "43675", 187.5f, 58 } // Technic Ribbed Hose 19L + }; + + lcMatrix33 RotationY = lcMatrix33RotationY(LC_PI / 2.0f); + + for (int InfoIdx = 0; InfoIdx < sizeof(RibbedHoseInfo) / sizeof(RibbedHoseInfo[0]); InfoIdx++) + { + PieceInfo* Info = Library->FindPiece(RibbedHoseInfo[InfoIdx].PartID, NULL, false); + if (Info) + { + lcSynthInfo* SynthInfo = new lcSynthInfo(); + + float Length = RibbedHoseInfo[InfoIdx].Length; + SynthInfo->DefaultControlPoints[0] = lcMatrix44(RotationY, lcVector3(-Length, 0.0f, 0.0f)); + SynthInfo->DefaultControlPoints[1] = lcMatrix44(RotationY, lcVector3( Length, 0.0f, 0.0f)); + SynthInfo->DefaultStiffness = 80.0f; + SynthInfo->NumSections = RibbedHoseInfo[InfoIdx].NumSections; + + SynthInfo->Components[0].Transform = lcMatrix44Identity(); + SynthInfo->Components[0].Transform[1][1] = -1.0f; + strcpy(SynthInfo->Components[0].PartID, "79.DAT"); + SynthInfo->Components[0].Length = 6.25f; + SynthInfo->Components[1].Transform = lcMatrix44Identity(); + strcpy(SynthInfo->Components[1].PartID, "80.DAT"); + SynthInfo->Components[1].Length = 6.25f; + SynthInfo->Components[2].Transform = lcMatrix44Identity(); + strcpy(SynthInfo->Components[2].PartID, "79.DAT"); + SynthInfo->Components[2].Length = 6.25f; + Info->SetSynthInfo(SynthInfo); + } + } +} + +inline lcMatrix44 lcMatrix44LeoCADToLDraw(const lcMatrix44& Matrix) +{ + lcMatrix44 m; + + m.r[0] = lcVector4( Matrix[0][0], -Matrix[2][0], Matrix[1][0], 0.0f); + m.r[1] = lcVector4(-Matrix[0][2], Matrix[2][2], -Matrix[1][2], 0.0f); + m.r[2] = lcVector4( Matrix[0][1], -Matrix[2][1], Matrix[1][1], 0.0f); + m.r[3] = lcVector4( Matrix[3][0], -Matrix[3][2], Matrix[3][1], 1.0f); + + return m; +} + +#include "lc_file.h" + +lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray& ControlPoints) +{ + lcArray Sections; + float SectionLength = 0.0f; + + for (int ControlPointIdx = 0; ControlPointIdx < ControlPoints.GetSize() - 1; ControlPointIdx++) + { + lcVector3 SegmentControlPoints[4]; + + lcMatrix44 StartTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform); + lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx + 1].Transform); + + if (ControlPointIdx == 0) + { + StartTransform = lcMul(StartTransform, SynthInfo->Components[0].Transform); + Sections.Add(StartTransform); + SectionLength = SynthInfo->Components[0].Length; + } + + if (ControlPointIdx == ControlPoints.GetSize() - 2) + EndTransform = lcMul(EndTransform, lcMatrix44(lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, -1.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f))); + + SegmentControlPoints[0] = StartTransform.GetTranslation(); + SegmentControlPoints[1] = lcMul31(lcVector3(0.0f, ControlPoints[ControlPointIdx].Stiffness, 0.0f), StartTransform); + SegmentControlPoints[2] = lcMul31(lcVector3(0.0f, -ControlPoints[ControlPointIdx + 1].Stiffness, 0.0f), EndTransform); + SegmentControlPoints[3] = EndTransform.GetTranslation(); + + float PointDistance = lcLength(SegmentControlPoints[3] - SegmentControlPoints[0]); + float PointDot = lcDot(SegmentControlPoints[1], SegmentControlPoints[2]); + + if ((PointDistance < ControlPoints[ControlPointIdx].Stiffness + ControlPoints[ControlPointIdx + 1].Stiffness) && (PointDot <= 0.001f)) + { + float Scale = 1.0f / (ControlPoints[ControlPointIdx].Stiffness + ControlPoints[ControlPointIdx + 1].Stiffness); + + SegmentControlPoints[1] = lcMul31(lcVector3(0.0f, ControlPoints[ControlPointIdx].Stiffness * Scale, 0.0f), StartTransform); + SegmentControlPoints[2] = lcMul31(lcVector3(0.0f, -ControlPoints[ControlPointIdx + 1].Stiffness * Scale, 0.0f), EndTransform); + } + + const int NumCurvePoints = 8192; + lcArray CurvePoints; + CurvePoints.AllocGrow(NumCurvePoints); + + for (int PointIdx = 0; PointIdx < NumCurvePoints; PointIdx++) + { + float t = (float)PointIdx / (float)(NumCurvePoints - 1); + float it = 1.0f - t; + + lcVector3 Position = it * it * it * SegmentControlPoints[0] + it * it * 3.0f * t * SegmentControlPoints[1] + it * 3.0 * t * t * SegmentControlPoints[2] + t * t * t * SegmentControlPoints[3]; + CurvePoints.Add(Position); + } + + int CurrentPointIndex = 0; + + lcVector3 StartUp(lcMul30(lcVector3(1.0f, 0.0f, 0.0f), StartTransform)); + lcVector3 EndUp(lcMul30(lcVector3(1.0f, 0.0f, 0.0f), EndTransform)); + lcVector4 UpRotation; + float UpDot = lcDot(StartUp, EndUp); + + if (UpDot < 0.99f) + UpRotation = lcVector4(lcCross(StartUp, EndUp), acosf(UpDot)); + else + UpRotation = lcVector4(0.0f, 0.0f, 0.0f, 0.0f); + + float CurrentSegmentLength = 0.0f; + float TotalSegmentLength = 0.0f; + + for (int PointIdx = 0; PointIdx < CurvePoints.GetSize() - 1; PointIdx++) + TotalSegmentLength += lcLength(CurvePoints[CurrentPointIndex] - CurvePoints[CurrentPointIndex + 1]); + + while (CurrentPointIndex < CurvePoints.GetSize() - 1) + { + float Length = lcLength(CurvePoints[CurrentPointIndex] - CurvePoints[CurrentPointIndex + 1]); + CurrentSegmentLength += Length; + SectionLength -= Length; + CurrentPointIndex++; + + if (SectionLength > 0.0f) + continue; + + float t = (float)CurrentPointIndex / (float)(NumCurvePoints - 1); + float it = 1.0f - t; + + lcVector3 Tangent = -3.0f * it * it * SegmentControlPoints[0] + (3.0f * it * it - 6.0f * t * it) * SegmentControlPoints[1] + (-3.0f * t * t + 6.0f * t * it) * SegmentControlPoints[2] + 3.0f * t * t * SegmentControlPoints[3]; + lcVector3 Up = lcMul(StartUp, lcMatrix33FromAxisAngle(lcVector3(UpRotation[0], UpRotation[1], UpRotation[2]), UpRotation[3] * (CurrentSegmentLength / TotalSegmentLength))); + lcVector3 Side = lcCross(Tangent, Up); + Up = lcCross(Side, Tangent); + + Sections.Add(lcMatrix44(lcMatrix33(lcNormalize(Up), lcNormalize(Tangent), lcNormalize(Side)), CurvePoints[CurrentPointIndex])); + + if (Sections.GetSize() == SynthInfo->NumSections + 2) + break; + + if (Sections.GetSize() < SynthInfo->NumSections + 1) + SectionLength += SynthInfo->Components[1].Length; + else + SectionLength += SynthInfo->Components[2].Length; + } + } + + while (Sections.GetSize() < SynthInfo->NumSections + 2) + { + lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPoints.GetSize() - 1].Transform); + EndTransform = lcMul(EndTransform, lcMatrix44(lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, -1.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f))); + lcVector3 Position = lcMul31(lcVector3(0.0f, SectionLength, 0.0f), EndTransform); + EndTransform.SetTranslation(Position); + Sections.Add(EndTransform); + + if (Sections.GetSize() < SynthInfo->NumSections + 1) + SectionLength += SynthInfo->Components[1].Length; + else + SectionLength += SynthInfo->Components[2].Length; + } + + // todo: rewrite this to pass the parts directly + + lcMemFile f; + + for (int i = 0; i < Sections.GetSize(); i++) + { + char str[256]; + + const lcMatrix44& Transform = Sections[i]; + const char* Name; + if (i == 0) + Name = SynthInfo->Components[0].PartID; + else if (i == Sections.GetSize() - 1) + Name = SynthInfo->Components[2].PartID; + else + Name = SynthInfo->Components[1].PartID; + + sprintf(str, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2], + Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], + Transform[0][2], Transform[1][2], Transform[2][2], + Name); + + f.WriteBuffer(str, strlen(str)); + } + + f.WriteU8(0); + + lcLibraryMeshData MeshData; + lcArray TextureStack; + f.Seek(0, SEEK_SET); + + const char* OldLocale = setlocale(LC_NUMERIC, "C"); + bool Ret = lcGetPiecesLibrary()->ReadMeshData(f, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED, false); + setlocale(LC_NUMERIC, OldLocale); + + if (Ret) + return lcGetPiecesLibrary()->CreateMesh(NULL, MeshData); + + return NULL; +} diff --git a/common/lc_synth.h b/common/lc_synth.h new file mode 100644 index 00000000..9d8ee0b2 --- /dev/null +++ b/common/lc_synth.h @@ -0,0 +1,26 @@ +#ifndef _LC_SYNTH_H_ +#define _LC_SYNTH_H_ + +#include "lc_math.h" +#include "piece.h" +#include "pieceinf.h" + +struct lcSynthComponent +{ + char PartID[LC_PIECE_NAME_LEN]; + lcMatrix44 Transform; + float Length; +}; + +struct lcSynthInfo +{ + lcMatrix44 DefaultControlPoints[2]; + lcSynthComponent Components[3]; + float DefaultStiffness; + int NumSections; +}; + +void lcSynthInit(); +lcMesh* lcSynthCreateMesh(lcSynthInfo* SynthInfo, const lcArray& ControlPoints); + +#endif // _LC_SYNTH_H_ diff --git a/common/piece.cpp b/common/piece.cpp index 3eaeda35..a1a2bd9f 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -15,6 +15,7 @@ #include "lc_library.h" #include "lc_context.h" #include "lc_qutils.h" +#include "lc_synth.h" #define LC_PIECE_CONTROL_POINT_SIZE 10.0f @@ -50,19 +51,21 @@ void lcPiece::SetPieceInfo(PieceInfo* Info) if (mPieceInfo) mPieceInfo->AddRef(); - if (0) // todo: get control points from the piece info + mControlPoints.RemoveAll(); + delete mMesh; + mMesh = NULL; + + lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : NULL; + + if (SynthInfo) { mControlPoints.SetSize(2); - mControlPoints[0].Position = lcVector3(0, 0, -30); - mControlPoints[1].Position = lcVector3(0, 0, 30); + mControlPoints[0].Transform = SynthInfo->DefaultControlPoints[0]; + mControlPoints[0].Stiffness = SynthInfo->DefaultStiffness; + mControlPoints[1].Transform = SynthInfo->DefaultControlPoints[1]; + mControlPoints[1].Stiffness = SynthInfo->DefaultStiffness; UpdateMesh(); } - else - { - mControlPoints.RemoveAll(); - delete mMesh; - mMesh = NULL; - } } void lcPiece::SaveLDraw(QTextStream& Stream) const @@ -428,7 +431,19 @@ void lcPiece::RemoveTime(lcStep Start, lcStep Time) void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const { - if (mPieceInfo->MinIntersectDist(mModelWorld, ObjectRayTest.Start, ObjectRayTest.End, ObjectRayTest.Distance)) + lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mModelWorld); + lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix); + lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix); + + if (mMesh) + { + if (mMesh->MinIntersectDist(Start, End, ObjectRayTest.Distance)) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_PIECE_SECTION_POSITION; + } + } + else if (mPieceInfo->MinIntersectDist(Start, End, ObjectRayTest.Distance)) { ObjectRayTest.ObjectSection.Object = const_cast(this); ObjectRayTest.ObjectSection.Section = LC_PIECE_SECTION_POSITION; @@ -436,20 +451,17 @@ void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const if (AreControlPointsVisible()) { - lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mModelWorld); - lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix); - lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix); + lcVector3 Min(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); + lcVector3 Max(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); for (int ControlPointIdx = 0; ControlPointIdx < mControlPoints.GetSize(); ControlPointIdx++) { - lcVector3 Min(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); - lcVector3 Max(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); - - Min += mControlPoints[ControlPointIdx].Position; - Max += mControlPoints[ControlPointIdx].Position; + lcMatrix44 InverseTransform = lcMatrix44AffineInverse(mControlPoints[ControlPointIdx].Transform); + lcVector3 PointStart = lcMul31(Start, InverseTransform); + lcVector3 PointEnd = lcMul31(End, InverseTransform); float Distance; - if (!lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, NULL) || (Distance >= ObjectRayTest.Distance)) + if (!lcBoundingBoxRayIntersectDistance(Min, Max, PointStart, PointEnd, &Distance, NULL) || (Distance >= ObjectRayTest.Distance)) continue; ObjectRayTest.ObjectSection.Object = const_cast(this); @@ -548,31 +560,30 @@ void lcPiece::DrawInterface(lcContext* Context) const if (AreControlPointsVisible()) { + float Verts[8 * 3]; + float* CurVert = Verts; + + lcVector3 Min(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); + lcVector3 Max(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); + + *CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2]; + *CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2]; + *CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2]; + *CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2]; + *CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2]; + *CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2]; + *CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2]; + *CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2]; + + const GLushort Indices[36] = + { + 0, 1, 2, 0, 2, 3, 7, 6, 5, 7, 5, 4, 0, 1, 5, 0, 5, 4, + 2, 3, 7, 2, 7, 6, 0, 3, 7, 0, 7, 4, 1, 2, 6, 1, 6, 5 + }; + for (int ControlPointIdx = 0; ControlPointIdx < mControlPoints.GetSize(); ControlPointIdx++) { - float Verts[8 * 3]; - float* CurVert = Verts; - - lcVector3 Min(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); - lcVector3 Max(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); - - Min += mControlPoints[ControlPointIdx].Position; - Max += mControlPoints[ControlPointIdx].Position; - - *CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2]; - *CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2]; - *CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2]; - *CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2]; - *CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2]; - *CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2]; - *CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2]; - *CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2]; - - const GLushort Indices[36] = - { - 0, 1, 2, 0, 2, 3, 7, 6, 5, 7, 5, 4, 0, 1, 5, 0, 5, 4, - 2, 3, 7, 2, 7, 6, 0, 3, 7, 0, 7, 4, 1, 2, 6, 1, 6, 5 - }; + Context->SetWorldMatrix(lcMul(mControlPoints[ControlPointIdx].Transform, mModelWorld)); Context->SetVertexBufferPointer(Verts); Context->SetVertexFormat(0, 3, 0, 0); @@ -616,13 +627,13 @@ void lcPiece::AddRenderMeshes(lcScene& Scene, bool DrawInterface) const RenderMesh.Distance = fabsf(lcMul31(mModelWorld[3], Scene.mViewMatrix).z); RenderMesh.LodIndex = RenderMesh.Mesh->GetLodIndex(RenderMesh.Distance); -// bool Translucent = lcIsColorTranslucent(mColorIndex); + bool Translucent = lcIsColorTranslucent(mColorIndex); -// if ((mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent)) + if ((mPieceInfo->mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent)) Scene.mOpaqueMeshes.Add(RenderMesh); -// if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent)) -// Scene.mTranslucentMeshes.Add(RenderMesh); + if ((mPieceInfo->mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && Translucent)) + Scene.mTranslucentMeshes.Add(RenderMesh); } if (Selected) @@ -646,7 +657,12 @@ void lcPiece::Move(lcStep Step, bool AddKey, const lcVector3& Distance) int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_1; if (ControlPointIndex >= 0 && ControlPointIndex < mControlPoints.GetSize()) - mControlPoints[ControlPointIndex].Position += Distance; + { + lcMatrix33 InverseWorldMatrix = lcMatrix33AffineInverse(lcMatrix33(mModelWorld)); + lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform; + + Transform.SetTranslation(Transform.GetTranslation() + lcMul(Distance, InverseWorldMatrix)); + } UpdateMesh(); } @@ -654,21 +670,45 @@ void lcPiece::Move(lcStep Step, bool AddKey, const lcVector3& Distance) void lcPiece::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame) { - lcVector3 Distance = mModelWorld.GetTranslation() - Center; - lcMatrix33 LocalToWorldMatrix = lcMatrix33(mModelWorld); + lcuint32 Section = GetFocusSection(); - lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); - lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix); + if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID) + { + lcVector3 Distance = mModelWorld.GetTranslation() - Center; + lcMatrix33 LocalToWorldMatrix = lcMatrix33(mModelWorld); - lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix); + lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); + lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix); - Distance = lcMul(Distance, WorldToLocalMatrix); - Distance = lcMul(Distance, NewLocalToWorldMatrix); + lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix); - NewLocalToWorldMatrix.Orthonormalize(); + Distance = lcMul(Distance, WorldToLocalMatrix); + Distance = lcMul(Distance, NewLocalToWorldMatrix); - SetPosition(Center + Distance, Step, AddKey); - SetRotation(NewLocalToWorldMatrix, Step, AddKey); + NewLocalToWorldMatrix.Orthonormalize(); + + SetPosition(Center + Distance, Step, AddKey); + SetRotation(NewLocalToWorldMatrix, Step, AddKey); + } + else + { + int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_1; + + if (ControlPointIndex >= 0 && ControlPointIndex < mControlPoints.GetSize()) + { + lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform; + lcMatrix33 PieceWorldMatrix(mModelWorld); + lcMatrix33 LocalToWorldMatrix = lcMul(lcMatrix33(Transform), PieceWorldMatrix); + + lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); + lcMatrix33 NewLocalToWorldMatrix = lcMul(lcMul(LocalToFocusMatrix, RotationMatrix), lcMatrix33AffineInverse(PieceWorldMatrix)); + + NewLocalToWorldMatrix.Orthonormalize(); + Transform = lcMatrix44(NewLocalToWorldMatrix, Transform.GetTranslation()); + } + + UpdateMesh(); + } } void lcPiece::MovePivotPoint(const lcVector3& Distance) @@ -747,46 +787,5 @@ void lcPiece::UpdatePosition(lcStep Step) void lcPiece::UpdateMesh() { delete mMesh; - - lcuint16 NumSections[LC_NUM_MESH_LODS] = { 1, 1 }; - - mMesh = new lcMesh(); - mMesh->Create(NumSections, 2, 0, 2); - - NumSections[0] = 2; - NumSections[1] = 2; - - for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++) - { - lcMeshSection& Section = mMesh->mLods[LodIdx].Sections[0]; - - Section.ColorIndex = gDefaultColor; - Section.PrimitiveType = GL_LINES; - Section.NumIndices = 2; - Section.Texture = NULL; - Section.IndexOffset = 0; - } - - lcuint16* Index = (lcuint16*)mMesh->mIndexData; - *Index++ = 0; - *Index++ = 1; - - lcVertex* Verts = (lcVertex*)mMesh->mVertexData; - Verts[0].Position = mControlPoints[0].Position; - Verts[1].Position = mControlPoints[1].Position; - - lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX, -FLT_MAX); - - Min = lcMin(mControlPoints[0].Position, Min); - Min = lcMin(mControlPoints[1].Position, Min); - - Max = lcMax(mControlPoints[0].Position, Max); - Max = lcMax(mControlPoints[1].Position, Max); - - Min -= lcVector3(5.0f, 5.0f, 5.0f); - Max += lcVector3(5.0f, 5.0f, 5.0f); - - mMesh->mRadius = lcLength(Max - Min) / 2.0f; - mMesh->mBoundingBox.Min = Min; - mMesh->mBoundingBox.Max = Max; + mMesh = lcSynthCreateMesh(mPieceInfo->GetSynthInfo(), mControlPoints); } diff --git a/common/piece.h b/common/piece.h index 2fa71dcb..28420010 100644 --- a/common/piece.h +++ b/common/piece.h @@ -48,7 +48,8 @@ enum lcPieceSection struct lcPieceControlPoint { - lcVector3 Position; + lcMatrix44 Transform; + float Stiffness; }; class lcPiece : public lcObject @@ -298,28 +299,28 @@ public: return mModelWorld.GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_1: - return lcMul31(mControlPoints[0].Position, mModelWorld); + return lcMul(mControlPoints[0].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_2: - return lcMul31(mControlPoints[1].Position, mModelWorld); + return lcMul(mControlPoints[1].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_3: - return lcMul31(mControlPoints[2].Position, mModelWorld); + return lcMul(mControlPoints[2].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_4: - return lcMul31(mControlPoints[3].Position, mModelWorld); + return lcMul(mControlPoints[3].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_5: - return lcMul31(mControlPoints[4].Position, mModelWorld); + return lcMul(mControlPoints[4].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_6: - return lcMul31(mControlPoints[5].Position, mModelWorld); + return lcMul(mControlPoints[5].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_7: - return lcMul31(mControlPoints[6].Position, mModelWorld); + return lcMul(mControlPoints[6].Transform, mModelWorld).GetTranslation(); case LC_PIECE_SECTION_CONTROL_POINT_8: - return lcMul31(mControlPoints[7].Position, mModelWorld); + return lcMul(mControlPoints[7].Transform, mModelWorld).GetTranslation(); } return lcVector3(0.0f, 0.0f, 0.0f); @@ -451,10 +452,27 @@ public: lcMatrix33 GetRelativeRotation() const { - if (mState & LC_PIECE_PIVOT_POINT_VALID) - return lcMatrix33(lcMul(mModelWorld, mPivotMatrix)); + lcuint32 Section = GetFocusSection(); + + if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID) + { + if (mState & LC_PIECE_PIVOT_POINT_VALID) + return lcMatrix33(lcMul(mModelWorld, mPivotMatrix)); + else + return lcMatrix33(mModelWorld); + } else - return lcMatrix33(mModelWorld); + { + int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_1; + + if (ControlPointIndex >= 0 && ControlPointIndex < mControlPoints.GetSize()) + { + lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform; + return lcMatrix33(lcMul(Transform, mModelWorld)); + } + + return lcMatrix33Identity(); + } } void ResetPivotPoint() @@ -494,7 +512,7 @@ protected: lcStep mStepShow; lcStep mStepHide; - lcuint8 mState; + lcuint32 mState; lcArray mControlPoints; lcMesh* mMesh; }; diff --git a/common/pieceinf.cpp b/common/pieceinf.cpp index 4a3cd2c9..665d1e34 100644 --- a/common/pieceinf.cpp +++ b/common/pieceinf.cpp @@ -8,6 +8,7 @@ #include "lc_application.h" #include "lc_model.h" #include "lc_context.h" +#include "lc_synth.h" #include "camera.h" #include @@ -20,12 +21,15 @@ PieceInfo::PieceInfo() mRefCount = 0; mMesh = NULL; mModel = NULL; + mSynthInfo = NULL; } PieceInfo::~PieceInfo() { if (mLoaded) Unload(); + + delete mSynthInfo; } QString PieceInfo::GetSaveID() const @@ -79,7 +83,7 @@ void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh) PieceFile.Seek(0, SEEK_SET); const char* OldLocale = setlocale(LC_NUMERIC, "C"); - bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED); + bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED, true); setlocale(LC_NUMERIC, OldLocale); if (Ret) @@ -154,32 +158,25 @@ void PieceInfo::Unload() lcGetPiecesLibrary()->RemovePiece(this); } -bool PieceInfo::MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const +bool PieceInfo::MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) const { - lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(WorldMatrix); - lcVector3 Start = lcMul31(WorldStart, InverseWorldMatrix); - lcVector3 End = lcMul31(WorldEnd, InverseWorldMatrix); - - const lcVector3& Min = mBoundingBox.Min; - const lcVector3& Max = mBoundingBox.Max; - - float Distance; - if (!lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, NULL) || (Distance >= MinDistance)) - return false; - - if (mFlags & LC_PIECE_PLACEHOLDER) - return true; - bool Intersect = false; - if (mMesh) + if (mFlags & (LC_PIECE_PLACEHOLDER | LC_PIECE_MODEL)) { - lcVector3 Intersection; - Intersect = mMesh->MinIntersectDist(Start, End, MinDistance, Intersection); + float Distance; + if (!lcBoundingBoxRayIntersectDistance(mBoundingBox.Min, mBoundingBox.Max, Start, End, &Distance, NULL) || (Distance >= MinDistance)) + return false; + + if (mFlags & LC_PIECE_PLACEHOLDER) + return true; + + if (mFlags & LC_PIECE_MODEL) + Intersect |= mModel->SubModelMinIntersectDist(Start, End, MinDistance); } - if (mFlags & LC_PIECE_MODEL) - Intersect |= mModel->SubModelMinIntersectDist(Start, End, MinDistance); + if (mMesh) + Intersect = mMesh->MinIntersectDist(Start, End, MinDistance); return Intersect; } diff --git a/common/pieceinf.h b/common/pieceinf.h index b450af8c..d494c049 100644 --- a/common/pieceinf.h +++ b/common/pieceinf.h @@ -15,6 +15,8 @@ #define LC_PIECE_NAME_LEN 256 +struct lcSynthInfo; + class PieceInfo { public: @@ -34,6 +36,16 @@ public: mBoundingBox.Max = Max; } + lcSynthInfo* GetSynthInfo() const + { + return mSynthInfo; + } + + void SetSynthInfo(lcSynthInfo* SynthInfo) + { + mSynthInfo = SynthInfo; + } + lcMesh* GetMesh() const { return mMesh; @@ -129,7 +141,7 @@ public: void SetPlaceholder(); void SetModel(lcModel* Model, bool UpdateMesh); bool IncludesModel(const lcModel* Model) const; - bool MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const; + bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) const; bool BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 Planes[6]) const; void GetPartsList(int DefaultColorIndex, lcArray& PartsList) const; void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcArray& ModelParts) const; @@ -149,6 +161,7 @@ protected: lcModel* mModel; lcMesh* mMesh; lcBoundingBox mBoundingBox; + lcSynthInfo* mSynthInfo; void Load(); void Unload(); diff --git a/leocad.pro b/leocad.pro index b6886c79..7fdd5622 100644 --- a/leocad.pro +++ b/leocad.pro @@ -143,6 +143,7 @@ SOURCES += common/view.cpp \ common/lc_model.cpp \ common/lc_profile.cpp \ common/lc_shortcuts.cpp \ + common/lc_synth.cpp \ common/lc_texture.cpp \ common/lc_zipfile.cpp \ common/image.cpp \ @@ -205,6 +206,7 @@ HEADERS += \ common/lc_model.h \ common/lc_profile.h \ common/lc_shortcuts.h \ + common/lc_synth.h \ common/lc_texture.h \ common/lc_zipfile.h \ common/image.h \