Added support to load loose library files.

This commit is contained in:
leo 2012-10-02 22:16:36 +00:00
parent 30ec8634d8
commit 08d7f05ffc
5 changed files with 288 additions and 186 deletions

View file

@ -33,7 +33,7 @@ PieceInfo* lcPiecesLibrary::FindPiece(const char* PieceName, bool CreatePlacehol
PieceInfo* lcPiecesLibrary::CreatePlaceholder(const char* PieceName)
{
PieceInfo* Info = new PieceInfo();
PieceInfo* Info = new PieceInfo(-1);
Info->CreatePlaceholder(PieceName);
mPieces.Add(Info);
@ -55,16 +55,15 @@ bool lcPiecesLibrary::Load(const char* SearchPath)
strcat(LibraryPath, "complete.zip");
if (!OpenArchive(LibraryPath))
return false;
if (!OpenDirectory(mLibraryPath))
return false;
const char* FileName = Sys_ProfileLoadString("Settings", "Categories", "");
if (!strlen(FileName) || !LoadCategories(FileName))
if (!FileName[0] || !LoadCategories(FileName))
ResetCategories();
SystemUpdateCategories(false);
mCategoriesModified = false;
Sys_ProfileSaveString("Settings", "PiecesLibrary", mLibraryPath);
return true;
@ -117,37 +116,22 @@ bool lcPiecesLibrary::OpenArchive(const char* FileName)
{
if (memcmp(Name + 12, "S/", 2))
{
PieceInfo* Info = new PieceInfo();
PieceInfo* Info = new PieceInfo(FileIdx);
mPieces.Add(Info);
strncpy(Info->m_strName, Name + 12, sizeof(Info->m_strName));
Info->m_strName[sizeof(Info->m_strName) - 1] = 0;
Info->m_nFlags = 0;
Info->m_nOffset = FileIdx;
}
else
{
lcLibraryPrimitive* Prim = new lcLibraryPrimitive();
lcLibraryPrimitive* Prim = new lcLibraryPrimitive(Name + 12, FileIdx, false, true);
mPrimitives.Add(Prim);
strncpy(Prim->mName, Name + 12, sizeof(Prim->mName));
Prim->mName[sizeof(Prim->mName) - 1] = 0;
Prim->mZipFileIndex = FileIdx;
Prim->mLoaded = false;
Prim->mStud = false;
Prim->mSubFile = true;
}
}
else if (!memcmp(Name + 6, "P/", 2))
{
lcLibraryPrimitive* Prim = new lcLibraryPrimitive();
lcLibraryPrimitive* Prim = new lcLibraryPrimitive(Name + 8, FileIdx, (memcmp(Prim->mName, "STU", 3) == 0), false);
mPrimitives.Add(Prim);
strncpy(Prim->mName, Name + 8, sizeof(Prim->mName));
Prim->mName[sizeof(Prim->mName) - 1] = 0;
Prim->mZipFileIndex = FileIdx;
Prim->mLoaded = false;
Prim->mStud = (memcmp(Prim->mName, "STU", 3) == 0);
Prim->mSubFile = false;
}
}
@ -157,7 +141,7 @@ bool lcPiecesLibrary::OpenArchive(const char* FileName)
{
PieceInfo* Info = mPieces[PieceInfoIndex];
mZipFile->ExtractFile(Info->m_nOffset, PieceFile, 256);
mZipFile->ExtractFile(Info->mZipFileIndex, PieceFile, 256);
PieceFile.Seek(0, SEEK_END);
PieceFile.WriteU8(0);
@ -180,30 +164,156 @@ bool lcPiecesLibrary::OpenArchive(const char* FileName)
return true;
}
bool lcPiecesLibrary::LoadPiece(const char* PieceName)
bool lcPiecesLibrary::OpenDirectory(const char* Path)
{
for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++)
{
PieceInfo* Info = mPieces[PieceInfoIndex];
char FileName[LC_MAXPATH];
ObjArray<String> FileList;
if (!strcmp(Info->m_strName, PieceName))
return LoadPiece(PieceInfoIndex);
strcpy(FileName, Path);
strcat(FileName, "parts/");
int PathLength = strlen(FileName);
Sys_GetFileList(FileName, FileList);
mPieces.RemoveAll();
mPieces.Expand(FileList.GetSize());
for (int FileIdx = 0; FileIdx < FileList.GetSize(); FileIdx++)
{
char Name[LC_PIECE_NAME_LEN];
const char* Src = (const char*)FileList[FileIdx] + PathLength;
char* Dst = Name;
while (*Src && Dst - Name < LC_PIECE_NAME_LEN)
{
if (*Src >= 'a' && *Src <= 'z')
*Dst = *Src + 'A' - 'a';
else if (*Src == '\\')
*Dst = '/';
else
*Dst = *Src;
Src++;
Dst++;
}
if (Dst - Name <= 4)
continue;
Dst -= 4;
if (memcmp(Dst, ".DAT", 4))
continue;
*Dst = 0;
lcDiskFile PieceFile;
if (!PieceFile.Open(FileList[FileIdx], "rt"))
continue;
char Line[1024];
if (!PieceFile.ReadLine(Line, sizeof(Line)))
continue;
PieceInfo* Info = new PieceInfo(-1);
mPieces.Add(Info);
Src = (char*)Line + 2;
Dst = Info->m_strDescription;
for (;;)
{
if (*Src != '\r' && *Src != '\n' && *Src && Dst - Info->m_strDescription < sizeof(Info->m_strDescription) - 1)
{
*Dst++ = *Src++;
continue;
}
*Dst = 0;
break;
}
strncpy(Info->m_strName, Name, sizeof(Info->m_strName));
Info->m_strName[sizeof(Info->m_strName) - 1] = 0;
}
return false;
if (!mPieces.GetSize())
return false;
const char* PrimitiveDirectories[] = { "p/", "p/48/", "parts/s/" };
bool SubFileDirectories[] = { false, false, true };
for (int DirectoryIdx = 0; DirectoryIdx < sizeof(PrimitiveDirectories) / sizeof(PrimitiveDirectories[0]); DirectoryIdx++)
{
strcpy(FileName, Path);
PathLength = strlen(FileName);
strcat(FileName, PrimitiveDirectories[DirectoryIdx]);
PathLength += strchr(PrimitiveDirectories[DirectoryIdx], '/') - PrimitiveDirectories[DirectoryIdx] + 1;
Sys_GetFileList(FileName, FileList);
for (int FileIdx = 0; FileIdx < FileList.GetSize(); FileIdx++)
{
char Name[LC_PIECE_NAME_LEN];
const char* Src = (const char*)FileList[FileIdx] + PathLength;
char* Dst = Name;
while (*Src && Dst - Name < LC_PIECE_NAME_LEN)
{
if (*Src >= 'a' && *Src <= 'z')
*Dst = *Src + 'A' - 'a';
else if (*Src == '\\')
*Dst = '/';
else
*Dst = *Src;
Src++;
Dst++;
}
if (Dst - Name <= 4)
continue;
Dst -= 4;
if (memcmp(Dst, ".DAT", 4))
continue;
*Dst = 0;
bool SubFile = SubFileDirectories[DirectoryIdx];
lcLibraryPrimitive* Prim = new lcLibraryPrimitive(Name, 0, !SubFile && (memcmp(Name, "STU", 3) == 0), SubFile);
mPrimitives.Add(Prim);
}
}
return true;
}
bool lcPiecesLibrary::LoadPiece(int PieceIndex)
bool lcPiecesLibrary::LoadPiece(PieceInfo* Info)
{
PieceInfo* Info = mPieces[PieceIndex];
lcMemFile PieceFile;
lcLibraryMeshData MeshData;
if (!mZipFile->ExtractFile(Info->m_nOffset, PieceFile))
return false;
if (mZipFile)
{
lcMemFile PieceFile;
if (!ReadMeshData(PieceFile, lcMatrix44Identity(), 16, MeshData))
return false;
if (!mZipFile->ExtractFile(Info->mZipFileIndex, PieceFile))
return false;
if (!ReadMeshData(PieceFile, lcMatrix44Identity(), 16, MeshData))
return false;
}
else
{
char FileName[LC_MAXPATH];
lcDiskFile PieceFile;
sprintf(FileName, "%sparts/%s.dat", mLibraryPath, Info->m_strName);
if (!PieceFile.Open(FileName, "rt"))
return false;
if (!ReadMeshData(PieceFile, lcMatrix44Identity(), 16, MeshData))
return false;
}
lcMesh* Mesh = new lcMesh();
@ -271,17 +381,17 @@ bool lcPiecesLibrary::LoadPiece(int PieceIndex)
if (SrcSection->mTriangles)
{
if (SrcSection->mColorCode == 16)
Info->m_nFlags |= LC_PIECE_HAS_DEFAULT;
Info->mFlags |= LC_PIECE_HAS_DEFAULT;
else
{
if (lcIsColorTranslucent(DstSection.ColorIndex))
Info->m_nFlags |= LC_PIECE_HAS_TRANSLUCENT;
Info->mFlags |= LC_PIECE_HAS_TRANSLUCENT;
else
Info->m_nFlags |= LC_PIECE_HAS_SOLID;
Info->mFlags |= LC_PIECE_HAS_SOLID;
}
}
else
Info->m_nFlags |= LC_PIECE_HAS_LINES;
Info->mFlags |= LC_PIECE_HAS_LINES;
NumIndices += DstSection.NumIndices;
}
@ -304,13 +414,33 @@ int lcPiecesLibrary::FindPrimitiveIndex(const char* Name)
bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex)
{
lcLibraryPrimitive* Primitive = mPrimitives[PrimitiveIndex];
lcMemFile File;
if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, File))
return false;
if (mZipFile)
{
lcMemFile PrimFile;
if (!ReadMeshData(File, lcMatrix44Identity(), 16, Primitive->mMeshData))
return false;
if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, PrimFile))
return false;
if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, Primitive->mMeshData))
return false;
}
else
{
char FileName[LC_MAXPATH];
lcDiskFile PrimFile;
if (Primitive->mSubFile)
sprintf(FileName, "%sparts/%s.dat", mLibraryPath, Primitive->mName);
else
sprintf(FileName, "%sp/%s.dat", mLibraryPath, Primitive->mName);
if (!PrimFile.Open(FileName, "rt"))
return false;
if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, Primitive->mMeshData))
return false;
}
Primitive->mLoaded = true;
@ -391,13 +521,32 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
MeshData.AddMeshData(Primitive->mMeshData, IncludeTransform, ColorCode);
else
{
lcMemFile IncludeFile;
if (mZipFile)
{
lcMemFile IncludeFile;
if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, IncludeFile))
continue;
if (!mZipFile->ExtractFile(Primitive->mZipFileIndex, IncludeFile))
continue;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
continue;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
continue;
}
else
{
char FileName[LC_MAXPATH];
lcDiskFile IncludeFile;
if (Primitive->mSubFile)
sprintf(FileName, "%sparts/%s.dat", mLibraryPath, Primitive->mName);
else
sprintf(FileName, "%sp/%s.dat", mLibraryPath, Primitive->mName);
if (!IncludeFile.Open(FileName, "rt"))
continue;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
continue;
}
}
}
else
@ -409,13 +558,29 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
if (strcmp(Info->m_strName, FileName))
continue;
lcMemFile IncludeFile;
if (mZipFile)
{
lcMemFile IncludeFile;
if (!mZipFile->ExtractFile(Info->m_nOffset, IncludeFile))
break;
if (!mZipFile->ExtractFile(Info->mZipFileIndex, IncludeFile))
break;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
break;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
break;
}
else
{
char FileName[LC_MAXPATH];
lcDiskFile IncludeFile;
sprintf(FileName, "%sparts/%s.dat", mLibraryPath, Info->m_strName);
if (!IncludeFile.Open(FileName, "rt"))
break;
if (!ReadMeshData(IncludeFile, IncludeTransform, ColorCode, MeshData))
break;
}
break;
}
@ -511,17 +676,26 @@ void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, const lcVector
switch (LineType)
{
case 4:
Section->mIndices.Add(Indices[2]);
Section->mIndices.Add(Indices[3]);
Section->mIndices.Add(Indices[0]);
if (Indices[0] != Indices[2] && Indices[0] != Indices[3] && Indices[2] != Indices[3])
{
Section->mIndices.Add(Indices[2]);
Section->mIndices.Add(Indices[3]);
Section->mIndices.Add(Indices[0]);
}
case 3:
Section->mIndices.Add(Indices[0]);
Section->mIndices.Add(Indices[1]);
Section->mIndices.Add(Indices[2]);
if (Indices[0] != Indices[1] && Indices[0] != Indices[2] && Indices[1] != Indices[2])
{
Section->mIndices.Add(Indices[0]);
Section->mIndices.Add(Indices[1]);
Section->mIndices.Add(Indices[2]);
}
break;
case 2:
Section->mIndices.Add(Indices[0]);
Section->mIndices.Add(Indices[1]);
if (Indices[0] != Indices[1])
{
Section->mIndices.Add(Indices[0]);
Section->mIndices.Add(Indices[1]);
}
break;
}
}
@ -903,7 +1077,7 @@ bool lcPiecesLibrary::SaveCategories()
bool lcPiecesLibrary::DoSaveCategories(bool AskName)
{
// Get the file name.
if (AskName || (strlen(mCategoriesFile) == 0))
if (AskName || !mCategoriesFile[0])
{
LC_FILESAVEDLG_OPTS opts;

View file

@ -53,6 +53,17 @@ public:
class lcLibraryPrimitive
{
public:
lcLibraryPrimitive(const char* Name, lcuint32 ZipFileIndex, bool Stud, bool SubFile)
{
strncpy(mName, Name, sizeof(mName));
mName[sizeof(mName) - 1] = 0;
mZipFileIndex = ZipFileIndex;
mLoaded = false;
mStud = Stud;
mSubFile = SubFile;
}
char mName[LC_MAXPATH];
lcuint32 mZipFileIndex;
bool mLoaded;
@ -77,6 +88,7 @@ public:
PieceInfo* FindPiece(const char* PieceName, bool CreatePlaceholderIfMissing);
PieceInfo* CreatePlaceholder(const char* PieceName);
bool LoadPiece(PieceInfo* Info);
bool PieceInCategory(PieceInfo* Info, const String& CategoryKeywords) const;
int GetFirstPieceCategory(PieceInfo* Info) const;
@ -91,15 +103,6 @@ public:
bool SaveCategories();
bool DoSaveCategories(bool AskName);
bool OpenArchive(const char* FileName);
bool LoadPiece(const char* PieceName);
bool LoadPiece(int PieceIndex);
int FindPrimitiveIndex(const char* Name);
bool LoadPrimitive(int PrimitiveIndex);
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcLibraryMeshData& MeshData);
PtrArray<PieceInfo> mPieces;
PtrArray<lcLibraryPrimitive> mPrimitives;
ObjArray<lcLibraryCategory> mCategories;
@ -107,6 +110,12 @@ public:
char mLibraryPath[LC_MAXPATH];
protected:
bool OpenArchive(const char* FileName);
bool OpenDirectory(const char* Path);
int FindPrimitiveIndex(const char* Name);
bool LoadPrimitive(int PrimitiveIndex);
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcLibraryMeshData& MeshData);
bool mCategoriesModified;
char mCategoriesFile[LC_MAXPATH];

View file

@ -2,47 +2,18 @@
#include "lc_math.h"
#include "lc_mesh.h"
#include "lc_colors.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "opengl.h"
#include "texture.h"
#include "pieceinf.h"
#include "project.h"
#include "lc_library.h"
#include "lc_application.h"
#define SIDES 16
static float sintbl[SIDES];
static float costbl[SIDES];
#define LC_MESH 1
#define LC_STUD 2
#define LC_STUD2 3
#define LC_STUD3 4
#define LC_STUD4 5
// measurements (in centimeters)
//#define LC_FLAT_HEIGHT 0.32f
//#define LC_BRICK_HEIGHT (3*LC_FLAT_HEIGHT)
//#define LC_BASEPLATE_HEIGHT (LC_FLAT_HEIGHT/2)
//#define LC_HALF_WIDE 0.4f
//#define LC_ONE_WIDE 0.8f
//#define LC_BRICK_WALL 0.125f
#define LC_STUD_HEIGHT 0.16f
#define LC_STUD_RADIUS 0.24f
#define LC_KNOB_RADIUS 0.32f
//#define LC_STUD_TECH_RADIUS (LC_FLAT_HEIGHT/2)
/////////////////////////////////////////////////////////////////////////////
// PieceInfo construction/destruction
PieceInfo::PieceInfo()
PieceInfo::PieceInfo(int ZipFileIndex)
{
mZipFileIndex = ZipFileIndex;
mFlags = 0;
mMesh = NULL;
m_nRef = 0;
m_nBoxList = 0;
mMesh = NULL;
}
PieceInfo::~PieceInfo()
@ -50,52 +21,6 @@ PieceInfo::~PieceInfo()
FreeInformation();
}
/////////////////////////////////////////////////////////////////////////////
// File I/O
void PieceInfo::LoadIndex(lcFile& file)
{
static bool init = false;
short sh[6];
short scale;
// Initialize sin/cos table
if (!init)
{
for (int i = 0; i < SIDES; i++)
{
sintbl[i] = (float)sin((LC_2PI*i)/(SIDES));
costbl[i] = (float)cos((LC_2PI*i)/(SIDES));
}
init = true;
}
file.ReadBuffer(m_strName, LC_PIECE_NAME_LEN);
file.ReadBuffer(m_strDescription, 64);
m_strDescription[64] = '\0';
file.ReadS16(sh, 6);
lcuint8 Flags;
file.ReadU8(&Flags, 1);
m_nFlags = Flags;
lcuint32 Groups; file.ReadU32(&Groups, 1);
file.ReadU32(&m_nOffset, 1);
file.ReadU32(&m_nSize, 1);
if (m_nFlags & LC_PIECE_SMALL)
scale = 10000;
else if (m_nFlags & LC_PIECE_MEDIUM)
scale = 1000;
else
scale = 100;
m_fDimensions[0] = (float)sh[0]/scale;
m_fDimensions[1] = (float)sh[1]/scale;
m_fDimensions[2] = (float)sh[2]/scale;
m_fDimensions[3] = (float)sh[3]/scale;
m_fDimensions[4] = (float)sh[4]/scale;
m_fDimensions[5] = (float)sh[5]/scale;
}
void PieceInfo::CreatePlaceholder(const char* Name)
{
strncpy(m_strName, Name, sizeof(m_strName));
@ -103,16 +28,7 @@ void PieceInfo::CreatePlaceholder(const char* Name)
strncpy(m_strDescription, Name, sizeof(m_strDescription));
m_strDescription[sizeof(m_strDescription)-1] = 0;
m_nFlags = LC_PIECE_PLACEHOLDER;
m_nOffset = 0;
m_nSize = 0;
m_fDimensions[0] = 0.4f;
m_fDimensions[1] = 0.4f;
m_fDimensions[2] = 0.16f;
m_fDimensions[3] = -0.4f;
m_fDimensions[4] = -0.4f;
m_fDimensions[5] = -0.96f;
mFlags = LC_PIECE_PLACEHOLDER;
}
void PieceInfo::AddRef()
@ -174,15 +90,25 @@ void PieceInfo::CreateBoxDisplayList()
void PieceInfo::LoadInformation()
{
if (m_nFlags & LC_PIECE_PLACEHOLDER)
FreeInformation();
if (mFlags & LC_PIECE_PLACEHOLDER)
{
mMesh = new lcMesh();
mMesh->CreateBox();
mFlags |= LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES;
m_fDimensions[0] = 0.4f;
m_fDimensions[1] = 0.4f;
m_fDimensions[2] = 0.16f;
m_fDimensions[3] = -0.4f;
m_fDimensions[4] = -0.4f;
m_fDimensions[5] = -0.96f;
}
else
{
FreeInformation();
lcGetPiecesLibrary()->LoadPiece(m_strName);
lcGetPiecesLibrary()->LoadPiece(this);
}
}

View file

@ -7,24 +7,19 @@
#endif
#include "lc_math.h"
#define LC_PIECE_COUNT 0x001 // Count this piece in the totals ?
#define LC_PIECE_LONGDATA_FILE 0x002 // unsigned long/short index
#define LC_PIECE_CCW 0x004 // Use back-face culling
#define LC_PIECE_SMALL 0x010 // scale = 10000
#define LC_PIECE_MEDIUM 0x020 // scale = 1000 (otherwise = 100)
#define LC_PIECE_PLACEHOLDER 0x040 // Placeholder for a piece not in the library.
#define LC_PIECE_HAS_DEFAULT 0x100 // Piece has triangles using the default color
#define LC_PIECE_HAS_SOLID 0x200 // Piece has triangles using a solid color
#define LC_PIECE_HAS_TRANSLUCENT 0x400 // Piece has triangles using a translucent color
#define LC_PIECE_HAS_LINES 0x800 // Piece has lines
#define LC_PIECE_HAS_DEFAULT 0x01 // Piece has triangles using the default color
#define LC_PIECE_HAS_SOLID 0x02 // Piece has triangles using a solid color
#define LC_PIECE_HAS_TRANSLUCENT 0x04 // Piece has triangles using a translucent color
#define LC_PIECE_HAS_LINES 0x08 // Piece has lines
#define LC_PIECE_PLACEHOLDER 0x10 // Placeholder for a piece not in the library.
#define LC_PIECE_NAME_LEN 256
class PieceInfo
{
public:
PieceInfo ();
~PieceInfo ();
public:
PieceInfo(int ZipFileIndex);
~PieceInfo();
bool IsPatterned() const
{
@ -67,7 +62,6 @@ class PieceInfo
CreateBoxDisplayList();
return m_nBoxList;
};
void LoadIndex(lcFile& file);
void CreatePlaceholder(const char* Name);
void AddRef();
void DeRef();
@ -79,9 +73,8 @@ public:
char m_strName[LC_PIECE_NAME_LEN];
char m_strDescription[128];
float m_fDimensions[6];
lcuint32 m_nOffset;
lcuint32 m_nSize;
lcuint32 m_nFlags;
lcuint32 mZipFileIndex;
lcuint32 mFlags;
protected:
int m_nRef;

View file

@ -1741,10 +1741,10 @@ void Project::RenderScenePieces(View* view)
bool Translucent = lcIsColorTranslucent(pPiece->mColorIndex);
PieceInfo* Info = pPiece->mPieceInfo;
if ((Info->m_nFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((Info->m_nFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
if ((Info->mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((Info->mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
OpaquePieces.AddSorted(pPiece, lcOpaqueRenderCompare, NULL);
if ((Info->m_nFlags & LC_PIECE_HAS_TRANSLUCENT) || ((Info->m_nFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
if ((Info->mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((Info->mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
{
lcVector3 Pos = lcMul31(pPiece->mPosition, WorldView);