2011-09-07 23:06:51 +02:00
|
|
|
// A piece object in the LeoCAD world.
|
|
|
|
//
|
|
|
|
|
2012-03-20 01:57:42 +01:00
|
|
|
#include "lc_global.h"
|
2012-04-14 01:41:58 +02:00
|
|
|
#include "lc_mesh.h"
|
2012-03-25 01:47:53 +01:00
|
|
|
#include "lc_colors.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "opengl.h"
|
|
|
|
#include "pieceinf.h"
|
|
|
|
#include "piece.h"
|
|
|
|
#include "group.h"
|
|
|
|
#include "project.h"
|
|
|
|
#include "lc_application.h"
|
2013-08-09 06:57:18 +02:00
|
|
|
#include "lc_library.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-28 03:07:18 +02:00
|
|
|
#define LC_PIECE_SAVE_VERSION 11 // LeoCAD 0.77
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
static LC_OBJECT_KEY_INFO piece_key_info[LC_PK_COUNT] =
|
|
|
|
{
|
|
|
|
{ "Position", 3, LC_PK_POSITION },
|
|
|
|
{ "Rotation", 4, LC_PK_ROTATION }
|
|
|
|
};
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Piece construction/destruction
|
|
|
|
|
|
|
|
Piece::Piece(PieceInfo* pPieceInfo)
|
2012-04-14 01:41:58 +02:00
|
|
|
: Object (LC_OBJECT_PIECE)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
m_pNext = NULL;
|
2012-05-17 23:52:20 +02:00
|
|
|
mPieceInfo = pPieceInfo;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nState = 0;
|
2012-03-28 03:07:18 +02:00
|
|
|
mColorIndex = 0;
|
|
|
|
mColorCode = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nStepShow = 1;
|
|
|
|
m_nStepHide = 255;
|
|
|
|
m_nFrameHide = 65535;
|
|
|
|
memset(m_strName, 0, sizeof(m_strName));
|
|
|
|
m_pGroup = NULL;
|
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
if (mPieceInfo != NULL)
|
|
|
|
mPieceInfo->AddRef();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
float *values[] = { mPosition, mRotation };
|
2012-04-14 01:41:58 +02:00
|
|
|
RegisterKeys (values, piece_key_info, LC_PK_COUNT);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-04-14 01:41:58 +02:00
|
|
|
float pos[3] = { 0, 0, 0 }, rot[4] = { 0, 0, 1, 0 };
|
|
|
|
ChangeKey (1, false, true, pos, LC_PK_POSITION);
|
|
|
|
ChangeKey (1, false, true, rot, LC_PK_ROTATION);
|
|
|
|
ChangeKey (1, true, true, pos, LC_PK_POSITION);
|
|
|
|
ChangeKey (1, true, true, rot, LC_PK_ROTATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Piece::~Piece()
|
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
if (mPieceInfo != NULL)
|
2012-10-12 01:55:55 +02:00
|
|
|
mPieceInfo->Release();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Piece save/load
|
|
|
|
|
|
|
|
// Use only when loading from a file
|
|
|
|
void Piece::SetPieceInfo(PieceInfo* pPieceInfo)
|
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
mPieceInfo = pPieceInfo;
|
|
|
|
mPieceInfo->AddRef();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
bool Piece::FileLoad(lcFile& file)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint8 version, ch;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
version = file.ReadU8();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (version > LC_PIECE_SAVE_VERSION)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (version > 8)
|
|
|
|
if (!Object::FileLoad (file))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (version < 9)
|
|
|
|
{
|
|
|
|
lcuint16 time;
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint8 type;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (version > 5)
|
|
|
|
{
|
|
|
|
lcuint32 keys;
|
2012-10-18 20:57:21 +02:00
|
|
|
float param[4];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU32(&keys, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
while (keys--)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadFloats(param, 4);
|
|
|
|
file.ReadU16(&time, 1);
|
|
|
|
file.ReadU8(&type, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
ChangeKey (time, false, true, param, type);
|
|
|
|
}
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU32(&keys, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
while (keys--)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadFloats(param, 4);
|
|
|
|
file.ReadU16(&time, 1);
|
|
|
|
file.ReadU8(&type, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
ChangeKey (time, true, true, param, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (version > 2)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&ch, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
while (ch--)
|
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
lcMatrix44 ModelWorld;
|
|
|
|
|
|
|
|
if (version > 3)
|
|
|
|
{
|
|
|
|
file.ReadFloats(ModelWorld, 16);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcVector3 Translation;
|
|
|
|
float Rotation[3];
|
|
|
|
file.ReadFloats(Translation, 3);
|
|
|
|
file.ReadFloats(Rotation, 3);
|
|
|
|
ModelWorld = lcMatrix44Translation(Translation);
|
|
|
|
ModelWorld = lcMul(lcMatrix44RotationZ(Rotation[2] * LC_DTOR), lcMul(lcMatrix44RotationY(Rotation[1] * LC_DTOR), lcMul(lcMatrix44RotationX(Rotation[0] * LC_DTOR), ModelWorld)));
|
|
|
|
}
|
|
|
|
|
|
|
|
lcuint8 b;
|
|
|
|
file.ReadU8(&b, 1);
|
|
|
|
time = b;
|
|
|
|
|
|
|
|
ChangeKey(1, false, true, ModelWorld.r[3], LC_PK_POSITION);
|
|
|
|
ChangeKey(1, true, true, ModelWorld.r[3], LC_PK_POSITION);
|
|
|
|
|
|
|
|
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(ModelWorld);
|
|
|
|
AxisAngle[3] *= LC_RTOD;
|
|
|
|
|
|
|
|
ChangeKey(time, false, true, AxisAngle, LC_PK_ROTATION);
|
|
|
|
ChangeKey(time, true, true, AxisAngle, LC_PK_ROTATION);
|
|
|
|
|
|
|
|
lcint32 bl;
|
|
|
|
file.ReadS32(&bl, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
lcVector3 Translation;
|
|
|
|
float Rotation[3];
|
|
|
|
file.ReadFloats(Translation, 3);
|
|
|
|
file.ReadFloats(Rotation, 3);
|
|
|
|
lcMatrix44 ModelWorld = lcMatrix44Translation(Translation);
|
|
|
|
ModelWorld = lcMul(lcMatrix44RotationZ(Rotation[2] * LC_DTOR), lcMul(lcMatrix44RotationY(Rotation[1] * LC_DTOR), lcMul(lcMatrix44RotationX(Rotation[0] * LC_DTOR), ModelWorld)));
|
|
|
|
|
|
|
|
ChangeKey(1, false, true, ModelWorld.r[3], LC_PK_POSITION);
|
|
|
|
ChangeKey(1, true, true, ModelWorld.r[3], LC_PK_POSITION);
|
|
|
|
|
|
|
|
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(ModelWorld);
|
|
|
|
AxisAngle[3] *= LC_RTOD;
|
|
|
|
ChangeKey(1, false, true, AxisAngle, LC_PK_ROTATION);
|
|
|
|
ChangeKey(1, true, true, AxisAngle, LC_PK_ROTATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Common to all versions.
|
2013-08-09 06:57:18 +02:00
|
|
|
char name[LC_PIECE_NAME_LEN];
|
2011-09-07 23:06:51 +02:00
|
|
|
if (version < 10)
|
|
|
|
{
|
|
|
|
memset(name, 0, LC_PIECE_NAME_LEN);
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadBuffer(name, 9);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadBuffer(name, LC_PIECE_NAME_LEN);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, true);
|
|
|
|
SetPieceInfo(pInfo);
|
|
|
|
|
2012-04-21 03:30:02 +02:00
|
|
|
// 11 (0.77)
|
2012-03-28 03:07:18 +02:00
|
|
|
if (version < 11)
|
|
|
|
{
|
|
|
|
lcuint8 Color;
|
|
|
|
|
|
|
|
file.ReadU8(&Color, 1);
|
|
|
|
|
|
|
|
if (version < 5)
|
2012-04-21 03:30:02 +02:00
|
|
|
mColorCode = lcGetColorCodeFromOriginalColor(Color);
|
|
|
|
else
|
|
|
|
mColorCode = lcGetColorCodeFromExtendedColor(Color);
|
2012-03-28 03:07:18 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
file.ReadU32(&mColorCode, 1);
|
|
|
|
mColorIndex = lcGetColorIndex(mColorCode);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&m_nStepShow, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (version > 1)
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&m_nStepHide, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
|
|
|
m_nStepHide = 255;
|
|
|
|
|
|
|
|
if (version > 5)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU16(&m_nFrameShow, 1);
|
|
|
|
file.ReadU16(&m_nFrameHide, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (version > 7)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&m_nState, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
Select (false, false, false);
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&ch, 1);
|
|
|
|
file.ReadBuffer(m_strName, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
lcint32 hide;
|
|
|
|
file.ReadS32(&hide, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (hide != 0)
|
|
|
|
m_nState |= LC_PIECE_HIDDEN;
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadBuffer(m_strName, 81);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 7 (0.64)
|
2012-03-23 00:44:56 +01:00
|
|
|
lcint32 i = -1;
|
2011-09-07 23:06:51 +02:00
|
|
|
if (version > 6)
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadS32(&i, 1);
|
2013-01-06 20:24:25 +01:00
|
|
|
m_pGroup = (Group*)(long)i;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_nFrameShow = 1;
|
|
|
|
m_nFrameHide = 65535;
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&ch, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (ch == 0)
|
|
|
|
m_pGroup = (Group*)-1;
|
|
|
|
else
|
2013-01-06 20:24:25 +01:00
|
|
|
m_pGroup = (Group*)(long)ch;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file.ReadU8(&ch, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (ch & 0x01)
|
|
|
|
m_nState |= LC_PIECE_HIDDEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Piece::FileSave(lcFile& file) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteU8(LC_PIECE_SAVE_VERSION);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
Object::FileSave (file);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
file.WriteBuffer(mPieceInfo->m_strName, LC_PIECE_NAME_LEN);
|
2012-03-28 03:07:18 +02:00
|
|
|
file.WriteU32(mColorCode);
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteU8(m_nStepShow);
|
|
|
|
file.WriteU8(m_nStepHide);
|
|
|
|
file.WriteU16(m_nFrameShow);
|
|
|
|
file.WriteU16(m_nFrameHide);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
// version 8
|
|
|
|
file.WriteU8(m_nState);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint8 Length = strlen(m_strName);
|
|
|
|
file.WriteU8(Length);
|
|
|
|
file.WriteBuffer(m_strName, Length);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
// version 7
|
|
|
|
lcint32 i;
|
|
|
|
|
|
|
|
if (m_pGroup != NULL)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Group* pGroups = lcGetActiveProject()->m_pGroups;
|
2012-03-23 00:44:56 +01:00
|
|
|
for (i = 0; pGroups; pGroups = pGroups->m_pNext)
|
|
|
|
{
|
|
|
|
if (m_pGroup == pGroups)
|
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
i = -1;
|
|
|
|
|
|
|
|
file.WriteS32(i);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-03-28 03:07:18 +02:00
|
|
|
void Piece::Initialize(float x, float y, float z, unsigned char nStep, unsigned short nFrame)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-03-28 03:07:18 +02:00
|
|
|
m_nFrameShow = nFrame;
|
|
|
|
m_nStepShow = nStep;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-28 03:07:18 +02:00
|
|
|
float pos[3] = { x, y, z }, rot[4] = { 0, 0, 1, 0 };
|
|
|
|
ChangeKey (1, false, true, pos, LC_PK_POSITION);
|
|
|
|
ChangeKey (1, false, true, rot, LC_PK_ROTATION);
|
|
|
|
ChangeKey (1, true, true, pos, LC_PK_POSITION);
|
|
|
|
ChangeKey (1, true, true, rot, LC_PK_ROTATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-28 03:07:18 +02:00
|
|
|
UpdatePosition (1, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::CreateName(Piece* pPiece)
|
|
|
|
{
|
|
|
|
int i, max = 0;
|
|
|
|
|
|
|
|
for (; pPiece; pPiece = pPiece->m_pNext)
|
2012-05-17 23:52:20 +02:00
|
|
|
if (strncmp (pPiece->m_strName, mPieceInfo->m_strDescription, strlen(mPieceInfo->m_strDescription)) == 0)
|
|
|
|
if (sscanf(pPiece->m_strName + strlen(mPieceInfo->m_strDescription), " #%d", &i) == 1)
|
2013-01-06 20:24:25 +01:00
|
|
|
if (i > max)
|
2011-09-07 23:06:51 +02:00
|
|
|
max = i;
|
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
sprintf (m_strName, "%s #%.2d", mPieceInfo->m_strDescription, max+1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::Select (bool bSelecting, bool bFocus, bool bMultiple)
|
|
|
|
{
|
|
|
|
if (bSelecting == true)
|
|
|
|
{
|
|
|
|
if (bFocus == true)
|
|
|
|
m_nState |= (LC_PIECE_FOCUSED|LC_PIECE_SELECTED);
|
|
|
|
else
|
|
|
|
m_nState |= LC_PIECE_SELECTED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (bFocus == true)
|
|
|
|
m_nState &= ~(LC_PIECE_FOCUSED);
|
|
|
|
else
|
|
|
|
m_nState &= ~(LC_PIECE_SELECTED|LC_PIECE_FOCUSED);
|
2013-01-06 20:24:25 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::InsertTime (unsigned short start, bool animation, unsigned short time)
|
|
|
|
{
|
|
|
|
if (animation)
|
|
|
|
{
|
|
|
|
if (m_nFrameShow >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nFrameShow = lcMin(m_nFrameShow + time, lcGetActiveProject()->GetTotalFrames());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nFrameHide >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nFrameHide = lcMin(m_nFrameHide + time, lcGetActiveProject()->GetTotalFrames());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nFrameShow > lcGetActiveProject()->GetCurrentTime())
|
|
|
|
Select (false, false, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_nStepShow >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nStepShow = lcMin(m_nStepShow + time, 255);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nStepHide >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nStepHide = lcMin(m_nStepHide + time, 255);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nStepShow > lcGetActiveProject()->GetCurrentTime ())
|
|
|
|
Select (false, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Object::InsertTime (start, animation, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::RemoveTime (unsigned short start, bool animation, unsigned short time)
|
|
|
|
{
|
|
|
|
if (animation)
|
|
|
|
{
|
|
|
|
if (m_nFrameShow >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nFrameShow = lcMax(m_nFrameShow - time, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nFrameHide == lcGetActiveProject()->GetTotalFrames())
|
|
|
|
m_nFrameHide = lcGetActiveProject()->GetTotalFrames();
|
|
|
|
else
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nFrameHide = lcMax(m_nFrameHide - time, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nFrameHide < lcGetActiveProject()->GetCurrentTime())
|
|
|
|
Select (false, false, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_nStepShow >= start)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nStepShow = lcMax(m_nStepShow - time, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nStepHide != 255)
|
2012-07-06 03:18:55 +02:00
|
|
|
m_nStepHide = lcMax(m_nStepHide - time, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nStepHide < lcGetActiveProject()->GetCurrentTime())
|
|
|
|
Select (false, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Object::RemoveTime (start, animation, time);
|
|
|
|
}
|
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
void Piece::MinIntersectDist(lcClickLine* ClickLine)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-17 01:50:40 +02:00
|
|
|
lcMatrix44 WorldModel = lcMatrix44AffineInverse(mModelWorld);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
lcVector3 Start = lcMul31(ClickLine->Start, WorldModel);
|
|
|
|
lcVector3 End = lcMul31(ClickLine->End, WorldModel);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
lcVector3 Min(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]);
|
|
|
|
lcVector3 Max(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]);
|
|
|
|
float Dist;
|
|
|
|
|
|
|
|
if (!lcBoundingBoxRayMinIntersectDistance(Min, Max, Start, End, &Dist, NULL) || (Dist >= ClickLine->MinDist))
|
|
|
|
return;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Intersection;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
if (mPieceInfo->mMesh->MinIntersectDist(Start, End, ClickLine->MinDist, Intersection))
|
|
|
|
ClickLine->Closest = this;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-08-23 20:47:37 +02:00
|
|
|
bool Piece::IntersectsVolume(const lcVector4 Planes[6]) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
// First check the bounding box for quick rejection.
|
2012-07-04 00:56:05 +02:00
|
|
|
lcVector3 Box[8] =
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-04 00:56:05 +02:00
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2])
|
2011-09-07 23:06:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Transform the planes to local space.
|
2012-07-04 00:56:05 +02:00
|
|
|
lcMatrix44 WorldToLocal = lcMatrix44FromAxisAngle(lcVector3(mRotation[0], mRotation[1], mRotation[2]), -mRotation[3] * LC_DTOR);
|
|
|
|
WorldToLocal.SetTranslation(lcMul31(lcVector3(-mPosition[0], -mPosition[1], -mPosition[2]), WorldToLocal));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-04 00:56:05 +02:00
|
|
|
const int NumPlanes = 6;
|
|
|
|
lcVector4 LocalPlanes[NumPlanes];
|
2011-09-07 23:06:51 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NumPlanes; i++)
|
|
|
|
{
|
2012-08-23 20:47:37 +02:00
|
|
|
lcVector3 PlaneNormal = lcMul30(Planes[i], WorldToLocal);
|
2012-07-04 00:56:05 +02:00
|
|
|
LocalPlanes[i] = lcVector4(PlaneNormal, Planes[i][3] - lcDot3(WorldToLocal[3], PlaneNormal));
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Start by testing trivial reject/accept cases.
|
|
|
|
int Outcodes[8];
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
Outcodes[i] = 0;
|
|
|
|
|
|
|
|
for (int j = 0; j < NumPlanes; j++)
|
|
|
|
{
|
2012-07-04 00:56:05 +02:00
|
|
|
if (lcDot3(Box[i], LocalPlanes[j]) + LocalPlanes[j][3] > 0)
|
2011-09-07 23:06:51 +02:00
|
|
|
Outcodes[i] |= 1 << j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int OutcodesOR = 0, OutcodesAND = 0x3f;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
OutcodesAND &= Outcodes[i];
|
|
|
|
OutcodesOR |= Outcodes[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// All corners outside the same plane.
|
|
|
|
if (OutcodesAND != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// All corners inside the volume.
|
|
|
|
if (OutcodesOR == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Partial intersection, so check if any triangles are inside.
|
2012-07-04 00:56:05 +02:00
|
|
|
bool Hit = mPieceInfo->mMesh->IntersectsPlanes(LocalPlanes);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-04-14 01:41:58 +02:00
|
|
|
return Hit;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
void Piece::Move(unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
mPosition[0] += dx;
|
|
|
|
mPosition[1] += dy;
|
|
|
|
mPosition[2] += dz;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_PK_POSITION);
|
|
|
|
|
|
|
|
mModelWorld.SetTranslation(mPosition);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Piece::IsVisible(unsigned short nTime, bool bAnimation)
|
|
|
|
{
|
|
|
|
if (m_nState & LC_PIECE_HIDDEN)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (bAnimation)
|
|
|
|
{
|
|
|
|
if (m_nFrameShow > nTime) return false;
|
|
|
|
if (m_nFrameHide < nTime) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_nStepShow > nTime) return false;
|
|
|
|
if ((m_nStepHide == 255) || (m_nStepHide > nTime))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::CompareBoundingBox(float box[6])
|
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
lcVector3 Points[8] =
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]),
|
|
|
|
lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2])
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
lcVector3 Point = lcMul31(Points[i], mModelWorld);
|
|
|
|
|
|
|
|
if (Point[0] < box[0]) box[0] = Point[0];
|
|
|
|
if (Point[1] < box[1]) box[1] = Point[1];
|
|
|
|
if (Point[2] < box[2]) box[2] = Point[2];
|
2012-07-21 00:57:43 +02:00
|
|
|
if (Point[0] > box[3]) box[3] = Point[0];
|
2012-05-17 23:52:20 +02:00
|
|
|
if (Point[1] > box[4]) box[4] = Point[1];
|
|
|
|
if (Point[2] > box[5]) box[5] = Point[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Group* Piece::GetTopGroup()
|
|
|
|
{
|
|
|
|
return m_pGroup ? m_pGroup->GetTopGroup() : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::DoGroup(Group* pGroup)
|
|
|
|
{
|
|
|
|
if (m_pGroup != NULL && m_pGroup != (Group*)-1 && m_pGroup > (Group*)0xFFFF)
|
|
|
|
m_pGroup->SetGroup(pGroup);
|
|
|
|
else
|
|
|
|
m_pGroup = pGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::UnGroup(Group* pGroup)
|
|
|
|
{
|
|
|
|
if ((m_pGroup == pGroup) || (pGroup == NULL))
|
|
|
|
m_pGroup = NULL;
|
|
|
|
else
|
|
|
|
if (m_pGroup != NULL)
|
|
|
|
m_pGroup->UnGroup(pGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recalculates current position and connections
|
|
|
|
void Piece::UpdatePosition(unsigned short nTime, bool bAnimation)
|
|
|
|
{
|
|
|
|
if (!IsVisible(nTime, bAnimation))
|
|
|
|
m_nState &= ~(LC_PIECE_SELECTED|LC_PIECE_FOCUSED);
|
|
|
|
|
|
|
|
CalculateKeys (nTime, bAnimation);
|
2012-05-17 23:52:20 +02:00
|
|
|
|
|
|
|
mModelWorld = lcMatrix44FromAxisAngle(lcVector3(mRotation[0], mRotation[1], mRotation[2]), mRotation[3] * LC_DTOR);
|
|
|
|
mModelWorld.SetTranslation(mPosition);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Piece::RenderBox(bool bHilite, float fLineWidth)
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
2012-05-17 23:52:20 +02:00
|
|
|
glMultMatrixf(mModelWorld);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (bHilite && ((m_nState & LC_PIECE_SELECTED) != 0))
|
|
|
|
{
|
2012-03-25 01:47:53 +01:00
|
|
|
if (m_nState & LC_PIECE_FOCUSED)
|
|
|
|
lcSetColorFocused();
|
|
|
|
else
|
|
|
|
lcSetColorSelected();
|
2011-09-07 23:06:51 +02:00
|
|
|
glLineWidth(2*fLineWidth);
|
|
|
|
glPushAttrib(GL_POLYGON_BIT);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
2012-05-17 23:52:20 +02:00
|
|
|
glCallList(mPieceInfo->GetBoxDisplayList());
|
2011-09-07 23:06:51 +02:00
|
|
|
glPopAttrib();
|
|
|
|
glLineWidth(fLineWidth);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-21 03:30:02 +02:00
|
|
|
lcSetColor(mColorIndex);
|
2012-05-17 23:52:20 +02:00
|
|
|
glCallList(mPieceInfo->GetBoxDisplayList());
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2012-03-25 01:47:53 +01:00
|
|
|
void Piece::Render(bool bLighting, bool bEdges)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
glPushMatrix();
|
2012-05-17 23:52:20 +02:00
|
|
|
glMultMatrixf(mModelWorld);
|
|
|
|
mPieceInfo->mMesh->Render(mColorIndex, (m_nState & LC_PIECE_SELECTED) != 0, (m_nState & LC_PIECE_FOCUSED) != 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
glPopMatrix();
|
|
|
|
}
|