3229 lines
90 KiB
C++
3229 lines
90 KiB
C++
// * This file is part of the COLOBOT source code
|
||
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
||
// *
|
||
// * This program is free software: you can redistribute it and/or modify
|
||
// * it under the terms of the GNU General Public License as published by
|
||
// * the Free Software Foundation, either version 3 of the License, or
|
||
// * (at your option) any later version.
|
||
// *
|
||
// * This program is distributed in the hope that it will be useful,
|
||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// * GNU General Public License for more details.
|
||
// *
|
||
// * You should have received a copy of the GNU General Public License
|
||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||
|
||
// model.cpp
|
||
|
||
|
||
#include <windows.h>
|
||
#include <stdio.h>
|
||
#include <d3d.h>
|
||
|
||
#include "common/struct.h"
|
||
#include "math/const.h"
|
||
#include "math/geometry.h"
|
||
#include "old/d3dengine.h"
|
||
#include "old/d3dmath.h"
|
||
#include "common/event.h"
|
||
#include "common/misc.h"
|
||
#include "common/iman.h"
|
||
#include "old/math3d.h"
|
||
#include "old/water.h"
|
||
#include "object/robotmain.h"
|
||
#include "ui/interface.h"
|
||
#include "ui/edit.h"
|
||
#include "ui/button.h"
|
||
#include "script/cmdtoken.h"
|
||
#include "old/modfile.h"
|
||
#include "old/model.h"
|
||
|
||
|
||
|
||
const int MAX_COLORS = 9;
|
||
|
||
static float table_color[MAX_COLORS*3] =
|
||
{
|
||
1.0f, 1.0f, 1.0f, // white
|
||
1.0f, 0.0f, 0.0f, // red
|
||
0.0f, 1.0f, 0.0f, // green
|
||
0.0f, 0.6f, 1.0f, // blue
|
||
1.0f, 1.0f, 0.0f, // yellow
|
||
0.0f, 1.0f, 1.0f, // cyan
|
||
1.0f, 0.0f, 1.0f, // magenta
|
||
0.3f, 0.3f, 0.3f, // grey
|
||
0.0f, 0.0f, 0.0f, // black
|
||
};
|
||
|
||
|
||
const int MAX_STATES = 10;
|
||
|
||
static int table_state[MAX_STATES] =
|
||
{
|
||
D3DSTATENORMAL,
|
||
D3DSTATEPART1,
|
||
D3DSTATEPART2,
|
||
D3DSTATEPART3,
|
||
D3DSTATEPART4,
|
||
D3DSTATE2FACE, // #5
|
||
D3DSTATETTw,
|
||
D3DSTATETTb,
|
||
D3DSTATETTw|D3DSTATE2FACE, // #8
|
||
D3DSTATETTb|D3DSTATE2FACE, // #9
|
||
};
|
||
|
||
|
||
const int MAX_NAMES = 23;
|
||
|
||
|
||
|
||
|
||
// Object's constructor.
|
||
|
||
CModel::CModel(CInstanceManager* iMan)
|
||
{
|
||
m_iMan = iMan;
|
||
|
||
m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
|
||
m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
|
||
|
||
m_modFile = new CModFile(m_iMan);
|
||
m_triangleTable = m_modFile->RetTriangleList();
|
||
|
||
m_textureRank = 0;
|
||
strcpy(m_textureName, "lemt.tga");
|
||
m_color = 0;
|
||
m_state = 0;
|
||
m_textureMode = 0;
|
||
m_textureRotate = 0;
|
||
m_bTextureMirrorX = false;
|
||
m_bTextureMirrorY = false;
|
||
m_texturePart = 0;
|
||
TexturePartUpdate();
|
||
|
||
m_bDisplayTransparent = false;
|
||
m_bDisplayOnlySelection = false;
|
||
InitView();
|
||
|
||
m_triangleSel1 = 0;
|
||
m_triangleSel2 = 0;
|
||
|
||
m_mode = 1;
|
||
m_oper = 'P';
|
||
|
||
m_secondTexNum = 0;
|
||
m_secondSubdiv = 1;
|
||
m_secondOffsetU = 0;
|
||
m_secondOffsetV = 0;
|
||
|
||
m_min = 0.0f;
|
||
m_max = 1000000.0f;
|
||
}
|
||
|
||
// Object's destructor.
|
||
|
||
CModel::~CModel()
|
||
{
|
||
delete m_modFile;
|
||
}
|
||
|
||
|
||
// You must call this procedure before changing the model interactively.
|
||
|
||
void CModel::StartUserAction()
|
||
{
|
||
Event event;
|
||
Math::Point pos, dim;
|
||
CButton* pb;
|
||
|
||
dim.x = 105.0f/640.0f;
|
||
dim.y = 18.0f/480.0f;
|
||
pos.x = 10.0f/640.0f;
|
||
pos.y = 450.0f/480.0f;
|
||
m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT1);
|
||
|
||
dim.x = 50.0f/640.0f;
|
||
pos.x = 125.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON1);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Load");
|
||
pos.x = 185.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON2);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Script");
|
||
pos.x = 245.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON3);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Read");
|
||
pos.x = 305.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON4);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Add");
|
||
pos.x = 365.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON5);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Write");
|
||
|
||
dim.x = 50.0f/640.0f;
|
||
dim.y = 18.0f/480.0f;
|
||
pos.x = 10.0f/640.0f;
|
||
pos.y = 425.0f/480.0f;
|
||
m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT2);
|
||
pos.x = 65.0f/640.0f;
|
||
pos.y = 425.0f/480.0f;
|
||
m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT3);
|
||
pos.x = 10.0f/640.0f;
|
||
pos.y = 400.0f/480.0f;
|
||
m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT4);
|
||
pos.x = 65.0f/640.0f;
|
||
pos.y = 400.0f/480.0f;
|
||
m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT5);
|
||
|
||
dim.x = 20.0f/640.0f;
|
||
dim.y = 20.0f/480.0f;
|
||
pos.y = 370.0f/480.0f;
|
||
pos.x = 10.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON10);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("P");
|
||
pos.x = 30.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON11);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("R");
|
||
pos.x = 50.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON12);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("Z");
|
||
pos.y = 350.0f/480.0f;
|
||
pos.x = 10.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON13);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("+X");
|
||
pos.x = 30.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON14);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("+Y");
|
||
pos.x = 50.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON15);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("+Z");
|
||
pos.y = 330.0f/480.0f;
|
||
pos.x = 10.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON16);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("-X");
|
||
pos.x = 30.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON17);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("-Y");
|
||
pos.x = 50.0f/640.0f;
|
||
pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON18);
|
||
pb->SetState(STATE_SIMPLY);
|
||
pb->SetName("-Z");
|
||
|
||
//? m_modFile->ReadModel("objects\\io.mod");
|
||
DeselectAll();
|
||
CurrentInit();
|
||
|
||
ZeroMemory(&event, sizeof(Event));
|
||
EventFrame(event);
|
||
|
||
m_engine->LoadAllTexture();
|
||
UpdateInfoText();
|
||
}
|
||
|
||
// You must call this procedure after modifing the model interactively.
|
||
|
||
void CModel::StopUserAction()
|
||
{
|
||
m_interface->DeleteControl(EVENT_EDIT1);
|
||
m_interface->DeleteControl(EVENT_EDIT2);
|
||
m_interface->DeleteControl(EVENT_EDIT3);
|
||
m_interface->DeleteControl(EVENT_EDIT4);
|
||
m_interface->DeleteControl(EVENT_EDIT5);
|
||
m_interface->DeleteControl(EVENT_BUTTON1);
|
||
m_interface->DeleteControl(EVENT_BUTTON2);
|
||
m_interface->DeleteControl(EVENT_BUTTON3);
|
||
m_interface->DeleteControl(EVENT_BUTTON4);
|
||
m_interface->DeleteControl(EVENT_BUTTON5);
|
||
m_interface->DeleteControl(EVENT_BUTTON10);
|
||
m_interface->DeleteControl(EVENT_BUTTON11);
|
||
m_interface->DeleteControl(EVENT_BUTTON12);
|
||
m_interface->DeleteControl(EVENT_BUTTON13);
|
||
m_interface->DeleteControl(EVENT_BUTTON14);
|
||
m_interface->DeleteControl(EVENT_BUTTON15);
|
||
m_interface->DeleteControl(EVENT_BUTTON16);
|
||
m_interface->DeleteControl(EVENT_BUTTON17);
|
||
m_interface->DeleteControl(EVENT_BUTTON18);
|
||
|
||
m_engine->SetInfoText(0, "");
|
||
m_engine->SetInfoText(1, "");
|
||
}
|
||
|
||
|
||
// Updates theeditable values for mapping textures.
|
||
|
||
void CModel::PutTextureValues()
|
||
{
|
||
CEdit* pe;
|
||
char s[100];
|
||
int value;
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
|
||
if ( pe != 0 )
|
||
{
|
||
value = (int)(m_textureSup.x*256.0f+0.5f);
|
||
sprintf(s, "%d", value);
|
||
pe->SetText(s);
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
|
||
if ( pe != 0 )
|
||
{
|
||
value = (int)(m_textureSup.y*256.0f+0.5f);
|
||
sprintf(s, "%d", value);
|
||
pe->SetText(s);
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
|
||
if ( pe != 0 )
|
||
{
|
||
value = (int)(m_textureInf.x*256.0f-0.5f);
|
||
sprintf(s, "%d", value);
|
||
pe->SetText(s);
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
|
||
if ( pe != 0 )
|
||
{
|
||
value = (int)(m_textureInf.y*256.0f-0.5f);
|
||
sprintf(s, "%d", value);
|
||
pe->SetText(s);
|
||
}
|
||
}
|
||
|
||
// Takes the editable values for mapping textures.
|
||
|
||
void CModel::GetTextureValues()
|
||
{
|
||
CEdit* pe;
|
||
char s[100];
|
||
int value;
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
|
||
if ( pe != 0 )
|
||
{
|
||
pe->GetText(s, 100);
|
||
sscanf(s, "%d", &value);
|
||
m_textureSup.x = ((float)value-0.5f)/256.0f;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
|
||
if ( pe != 0 )
|
||
{
|
||
pe->GetText(s, 100);
|
||
sscanf(s, "%d", &value);
|
||
m_textureSup.y = ((float)value-0.5f)/256.0f;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
|
||
if ( pe != 0 )
|
||
{
|
||
pe->GetText(s, 100);
|
||
sscanf(s, "%d", &value);
|
||
m_textureInf.x = ((float)value+0.5f)/256.0f;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
|
||
if ( pe != 0 )
|
||
{
|
||
pe->GetText(s, 100);
|
||
sscanf(s, "%d", &value);
|
||
m_textureInf.y = ((float)value+0.5f)/256.0f;
|
||
}
|
||
}
|
||
|
||
|
||
// Gives the model name.
|
||
|
||
void CModel::GetModelName(char *buffer)
|
||
{
|
||
CEdit* pe;
|
||
char s[100];
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
|
||
if ( pe == 0 )
|
||
{
|
||
strcpy(buffer, "objects\\io.mod");
|
||
}
|
||
else
|
||
{
|
||
pe->GetText(s, 100);
|
||
sprintf(buffer, "objects\\%s.mod", s);
|
||
}
|
||
}
|
||
|
||
// Gives the model name.
|
||
|
||
void CModel::GetDXFName(char *buffer)
|
||
{
|
||
CEdit* pe;
|
||
char s[100];
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
|
||
if ( pe == 0 )
|
||
{
|
||
strcpy(buffer, "models\\import.dxf");
|
||
}
|
||
else
|
||
{
|
||
pe->GetText(s, 100);
|
||
sprintf(buffer, "models\\%s.dxf", s);
|
||
}
|
||
}
|
||
|
||
// Gives the model name.
|
||
|
||
void CModel::GetScriptName(char *buffer)
|
||
{
|
||
CEdit* pe;
|
||
char s[100];
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
|
||
if ( pe == 0 )
|
||
{
|
||
strcpy(buffer, "objects\\script.txt");
|
||
}
|
||
else
|
||
{
|
||
pe->GetText(s, 100);
|
||
sprintf(buffer, "objects\\%s.txt", s);
|
||
}
|
||
}
|
||
|
||
// Indicates whether the edition name has focus.
|
||
|
||
bool CModel::IsEditFocus()
|
||
{
|
||
CEdit* pe;
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
|
||
if ( pe != 0 )
|
||
{
|
||
if ( pe->RetFocus() ) return true;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
|
||
if ( pe != 0 )
|
||
{
|
||
if ( pe->RetFocus() ) return true;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
|
||
if ( pe != 0 )
|
||
{
|
||
if ( pe->RetFocus() ) return true;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
|
||
if ( pe != 0 )
|
||
{
|
||
if ( pe->RetFocus() ) return true;
|
||
}
|
||
|
||
pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
|
||
if ( pe != 0 )
|
||
{
|
||
if ( pe->RetFocus() ) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
// Management of an event.
|
||
|
||
bool CModel::EventProcess(const Event &event)
|
||
{
|
||
char s[100];
|
||
int first, last;
|
||
|
||
switch( event.event )
|
||
{
|
||
case EVENT_FRAME:
|
||
EventFrame(event);
|
||
break;
|
||
|
||
case EVENT_KEYDOWN:
|
||
if ( IsEditFocus() )
|
||
break;
|
||
|
||
if ( event.param == '1' )
|
||
{
|
||
m_mode = 1;
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == '2' )
|
||
{
|
||
m_mode = 2;
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == '3' )
|
||
{
|
||
m_mode = 3;
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == VK_ADD ) // numpad?
|
||
{
|
||
if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
|
||
CurrentSearchNext(+1, (event.keyState & KS_CONTROL));
|
||
}
|
||
if ( event.param == VK_SUBTRACT ) // least numpad?
|
||
{
|
||
if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
|
||
CurrentSearchNext(-1, (event.keyState & KS_CONTROL));
|
||
}
|
||
if ( event.param == VK_NUMPAD0 )
|
||
{
|
||
CurrentSelect(false);
|
||
}
|
||
if ( event.param == VK_DECIMAL )
|
||
{
|
||
CurrentSelect(true);
|
||
}
|
||
if ( event.param == VK_END )
|
||
{
|
||
DeselectAll();
|
||
}
|
||
if ( event.param == VK_INSERT )
|
||
{
|
||
SelectAll();
|
||
}
|
||
if ( event.param == VK_BACK ) // Delete normal ?
|
||
{
|
||
SelectDelete();
|
||
}
|
||
if ( event.param == VK_SPACE )
|
||
{
|
||
m_bDisplayTransparent = !m_bDisplayTransparent;
|
||
m_bDisplayOnlySelection = false;
|
||
}
|
||
if ( event.param == 'H' )
|
||
{
|
||
m_bDisplayOnlySelection = !m_bDisplayOnlySelection;
|
||
m_bDisplayTransparent = false;
|
||
}
|
||
if ( m_mode == 1 )
|
||
{
|
||
if ( event.param == 'S' )
|
||
{
|
||
SmoothSelect();
|
||
}
|
||
if ( event.param == 'N' )
|
||
{
|
||
PlaneSelect();
|
||
}
|
||
if ( event.param == 'C' )
|
||
{
|
||
ColorSelect();
|
||
}
|
||
if ( event.param == 'V' )
|
||
{
|
||
m_color ++;
|
||
if ( m_color >= MAX_COLORS ) m_color = 0;
|
||
UpdateInfoText();
|
||
ColorSelect();
|
||
}
|
||
if ( event.param == 'J' )
|
||
{
|
||
StateSelect();
|
||
}
|
||
if ( event.param == 'K' )
|
||
{
|
||
m_state ++;
|
||
if ( m_state >= MAX_STATES ) m_state = 0;
|
||
UpdateInfoText();
|
||
StateSelect();
|
||
}
|
||
if ( event.param == 'M' )
|
||
{
|
||
m_textureMode ++;
|
||
if ( m_textureMode > 3 ) m_textureMode = 0;
|
||
UpdateInfoText();
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'Z' )
|
||
{
|
||
m_textureRotate ++;
|
||
if ( m_textureRotate > 2 ) m_textureRotate = 0;
|
||
UpdateInfoText();
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'X' )
|
||
{
|
||
m_bTextureMirrorX = !m_bTextureMirrorX;
|
||
UpdateInfoText();
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'Y' )
|
||
{
|
||
m_bTextureMirrorY = !m_bTextureMirrorY;
|
||
UpdateInfoText();
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'O' )
|
||
{
|
||
TextureRankChange(+1);
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'P' )
|
||
{
|
||
TexturePartChange(+1);
|
||
UpdateInfoText();
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'T' )
|
||
{
|
||
GetTextureValues();
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_textureInf, m_textureSup, m_textureName);
|
||
}
|
||
if ( event.param == 'E' )
|
||
{
|
||
Math::Point ti, ts;
|
||
ti.x = 0.00f;
|
||
ti.y = 0.00f;
|
||
ts.x = 0.00f;
|
||
ts.y = 0.00f;
|
||
MappingSelect(m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
ti, ts, "");
|
||
}
|
||
}
|
||
if ( m_mode == 2 )
|
||
{
|
||
if ( event.param == 'E' )
|
||
{
|
||
m_secondTexNum = 0;
|
||
UpdateInfoText();
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
}
|
||
if ( event.param == 'O' )
|
||
{
|
||
m_secondTexNum ++;
|
||
if ( m_secondTexNum > 10 ) m_secondTexNum = 1;
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'T' )
|
||
{
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
m_engine->LoadAllTexture();
|
||
}
|
||
if ( event.param == 'U' )
|
||
{
|
||
m_secondOffsetU += 45;
|
||
if ( m_secondOffsetU >= 360 ) m_secondOffsetU = 0;
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'V' )
|
||
{
|
||
m_secondOffsetV += 45;
|
||
if ( m_secondOffsetV >= 360 ) m_secondOffsetV = 0;
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'X' )
|
||
{
|
||
m_bTextureMirrorX = !m_bTextureMirrorX;
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'Y' )
|
||
{
|
||
m_bTextureMirrorY = !m_bTextureMirrorY;
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'S' )
|
||
{
|
||
m_secondSubdiv ++;
|
||
if ( m_secondSubdiv > 7 ) m_secondSubdiv = 1;
|
||
MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
|
||
UpdateInfoText();
|
||
}
|
||
}
|
||
if ( m_mode == 3 )
|
||
{
|
||
if ( event.param == 'M' )
|
||
{
|
||
if ( m_min == 0.0f && m_max == 1000000.0f )
|
||
{
|
||
m_min = 0.0f; m_max = 100.0f;
|
||
}
|
||
else if ( m_min == 0.0f && m_max == 100.0f )
|
||
{
|
||
m_min = 100.0f; m_max = 200.0f;
|
||
}
|
||
else if ( m_min == 100.0f && m_max == 200.0f )
|
||
{
|
||
m_min = 200.0f; m_max = 1000000.0f;
|
||
}
|
||
else if ( m_min == 200.0f && m_max == 1000000.0f )
|
||
{
|
||
m_min = 0.0f; m_max = 1000000.0f;
|
||
}
|
||
UpdateInfoText();
|
||
}
|
||
if ( event.param == 'C' )
|
||
{
|
||
MinMaxChange();
|
||
}
|
||
}
|
||
break;
|
||
|
||
case EVENT_BUTTON1: // import ?
|
||
GetDXFName(s);
|
||
m_modFile->ReadDXF(s, m_min, m_max);
|
||
DeselectAll();
|
||
CurrentInit();
|
||
EventFrame(event);
|
||
m_engine->LoadAllTexture();
|
||
break;
|
||
|
||
case EVENT_BUTTON2: // script ?
|
||
GetScriptName(s);
|
||
ReadScript(s);
|
||
DeselectAll();
|
||
CurrentInit();
|
||
EventFrame(event);
|
||
m_engine->LoadAllTexture();
|
||
break;
|
||
|
||
case EVENT_BUTTON3: // read ?
|
||
GetModelName(s);
|
||
m_modFile->ReadModel(s, true, false); // standard read with borders
|
||
DeselectAll();
|
||
CurrentInit();
|
||
EventFrame(event);
|
||
m_engine->LoadAllTexture();
|
||
break;
|
||
|
||
case EVENT_BUTTON4: // add ?
|
||
GetModelName(s);
|
||
first = m_modFile->RetTriangleUsed();
|
||
m_modFile->AddModel(s, first, true, false); // standard read with borders
|
||
last = m_modFile->RetTriangleUsed();
|
||
SelectZone(first, last);
|
||
EventFrame(event);
|
||
break;
|
||
|
||
case EVENT_BUTTON5: // write ?
|
||
GetModelName(s);
|
||
DeselectAll();
|
||
m_modFile->WriteModel(s);
|
||
break;
|
||
|
||
case EVENT_BUTTON10: // pos ?
|
||
m_oper = 'P';
|
||
break;
|
||
case EVENT_BUTTON11: // rotate ?
|
||
m_oper = 'R';
|
||
break;
|
||
case EVENT_BUTTON12: // zoom ?
|
||
m_oper = 'Z';
|
||
break;
|
||
|
||
case EVENT_BUTTON13: // +X ?
|
||
MoveSelect(Math::Vector(1.0f, 0.0f, 0.0f));
|
||
break;
|
||
case EVENT_BUTTON16: // -X ?
|
||
MoveSelect(Math::Vector(-1.0f, 0.0f, 0.0f));
|
||
break;
|
||
case EVENT_BUTTON14: // +Y ?
|
||
MoveSelect(Math::Vector(0.0f, 1.0f, 0.0f));
|
||
break;
|
||
case EVENT_BUTTON17: // -Y ?
|
||
MoveSelect(Math::Vector(0.0f, -1.0f, 0.0f));
|
||
break;
|
||
case EVENT_BUTTON15: // +Z ?
|
||
MoveSelect(Math::Vector(0.0f, 0.0f, 1.0f));
|
||
break;
|
||
case EVENT_BUTTON18: // -Z ?
|
||
MoveSelect(Math::Vector(0.0f, 0.0f, -1.0f));
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
// Drives the model.
|
||
|
||
bool CModel::EventFrame(const Event &event)
|
||
{
|
||
D3DMATERIAL7 matCurrent, matCurrenti, matCurrents, matTrans;
|
||
D3DMATERIAL7* pMat;
|
||
D3DVERTEX2 vertex[3];
|
||
char texName2[20];
|
||
int i, used, objRank, state;
|
||
|
||
m_time += event.rTime;
|
||
|
||
m_engine->FlushObject();
|
||
objRank = m_engine->CreateObject();
|
||
|
||
ZeroMemory(&matCurrent, sizeof(D3DMATERIAL7));
|
||
matCurrent.diffuse.r = 1.0f;
|
||
matCurrent.diffuse.g = 0.0f;
|
||
matCurrent.diffuse.b = 0.0f; // red
|
||
matCurrent.ambient.r = 0.5f;
|
||
matCurrent.ambient.g = 0.5f;
|
||
matCurrent.ambient.b = 0.5f;
|
||
|
||
ZeroMemory(&matCurrents, sizeof(D3DMATERIAL7));
|
||
matCurrents.diffuse.r = 1.0f;
|
||
matCurrents.diffuse.g = 1.0f;
|
||
matCurrents.diffuse.b = 0.0f; // yellow
|
||
matCurrents.ambient.r = 0.5f;
|
||
matCurrents.ambient.g = 0.5f;
|
||
matCurrents.ambient.b = 0.5f;
|
||
|
||
ZeroMemory(&matCurrenti, sizeof(D3DMATERIAL7));
|
||
matCurrenti.diffuse.r = 0.0f;
|
||
matCurrenti.diffuse.g = 0.0f;
|
||
matCurrenti.diffuse.b = 1.0f; // blue
|
||
matCurrenti.ambient.r = 0.5f;
|
||
matCurrenti.ambient.g = 0.5f;
|
||
matCurrenti.ambient.b = 0.5f;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( !m_triangleTable[i].bUsed ) continue;
|
||
|
||
if ( m_triangleTable[i].min != m_min ||
|
||
m_triangleTable[i].max != m_max ) continue;
|
||
|
||
pMat = &m_triangleTable[i].material;
|
||
state = D3DSTATENORMAL;
|
||
|
||
if ( i >= m_triangleSel1 &&
|
||
i <= m_triangleSel2 &&
|
||
(int)(m_time*10.0f)%2 == 0 )
|
||
{
|
||
pMat = &matCurrent;
|
||
}
|
||
else if ( m_triangleTable[i].bSelect &&
|
||
(int)(m_time*10.0f)%2 == 0 )
|
||
{
|
||
pMat = &matCurrents;
|
||
}
|
||
else
|
||
{
|
||
if ( m_bDisplayOnlySelection ) continue;
|
||
if ( m_bDisplayTransparent )
|
||
{
|
||
matTrans = m_triangleTable[i].material;
|
||
matTrans.diffuse.a = 0.1f; // very transparent
|
||
pMat = &matTrans;
|
||
state = D3DSTATETD;
|
||
}
|
||
}
|
||
|
||
if ( m_triangleTable[i].texNum2 == 0 )
|
||
{
|
||
m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
|
||
*pMat, state,
|
||
m_triangleTable[i].texName, "",
|
||
0.0f, 1000000.0f, false);
|
||
}
|
||
else
|
||
{
|
||
sprintf(texName2, "dirty%.2d.tga", m_triangleTable[i].texNum2);
|
||
m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
|
||
*pMat, state|D3DSTATEDUALb,
|
||
m_triangleTable[i].texName, texName2,
|
||
0.0f, 1000000.0f, false);
|
||
}
|
||
|
||
if ( m_bDisplayTransparent && // draws inside?
|
||
i >= m_triangleSel1 &&
|
||
i <= m_triangleSel2 )
|
||
{
|
||
vertex[0] = m_triangleTable[i].p3;
|
||
vertex[1] = m_triangleTable[i].p2;
|
||
vertex[2] = m_triangleTable[i].p1;
|
||
|
||
m_engine->AddTriangle(objRank, vertex, 3,
|
||
matCurrenti, D3DSTATENORMAL,
|
||
m_triangleTable[i].texName, "",
|
||
0.0f, 1000000.0f, false);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
// Gives a vertex.
|
||
|
||
bool CModel::GetVertex(int rank, D3DVERTEX2 &vertex)
|
||
{
|
||
if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
|
||
if ( !m_triangleTable[rank/3].bUsed ) return false;
|
||
|
||
if ( !m_triangleTable[rank/3].bSelect ) return false;
|
||
|
||
if ( rank%3 == 0 )
|
||
{
|
||
vertex = m_triangleTable[rank/3].p1;
|
||
return true;
|
||
}
|
||
if ( rank%3 == 1 )
|
||
{
|
||
vertex = m_triangleTable[rank/3].p2;
|
||
return true;
|
||
}
|
||
if ( rank%3 == 2 )
|
||
{
|
||
vertex = m_triangleTable[rank/3].p3;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// Modifies a vertex.
|
||
|
||
bool CModel::SetVertex(int rank, D3DVERTEX2 &vertex)
|
||
{
|
||
if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
|
||
if ( !m_triangleTable[rank/3].bUsed ) return false;
|
||
|
||
if ( !m_triangleTable[rank/3].bSelect ) return false;
|
||
|
||
if ( rank%3 == 0 )
|
||
{
|
||
m_triangleTable[rank/3].p1 = vertex;
|
||
return true;
|
||
}
|
||
if ( rank%3 == 1 )
|
||
{
|
||
m_triangleTable[rank/3].p2 = vertex;
|
||
return true;
|
||
}
|
||
if ( rank%3 == 2 )
|
||
{
|
||
m_triangleTable[rank/3].p3 = vertex;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// Smoothed normals selected triangles.
|
||
|
||
void CModel::SmoothSelect()
|
||
{
|
||
char* bDone;
|
||
int index[100];
|
||
int used, i, j, rank;
|
||
D3DVERTEX2 vi, vj;
|
||
Math::Vector sum;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
|
||
bDone = (char*)malloc(used*3*sizeof(char));
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
bDone[i] = false;
|
||
}
|
||
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
bDone[i] = true;
|
||
rank = 0;
|
||
index[rank++] = i;
|
||
if ( !GetVertex(i, vi) ) continue;
|
||
|
||
for ( j=0 ; j<used*3 ; j++ )
|
||
{
|
||
if ( bDone[j] ) continue;
|
||
if ( !GetVertex(j, vj) ) continue;
|
||
if ( vj.x == vi.x &&
|
||
vj.y == vi.y &&
|
||
vj.z == vi.z )
|
||
{
|
||
bDone[j] = true;
|
||
index[rank++] = j;
|
||
if ( rank >= 100 ) break;
|
||
}
|
||
}
|
||
|
||
sum.x = 0;
|
||
sum.y = 0;
|
||
sum.z = 0;
|
||
for ( j=0 ; j<rank ; j++ )
|
||
{
|
||
GetVertex(index[j], vj);
|
||
sum.x += vj.nx;
|
||
sum.y += vj.ny;
|
||
sum.z += vj.nz;
|
||
}
|
||
sum = Normalize(sum);
|
||
|
||
for ( j=0 ; j<rank ; j++ )
|
||
{
|
||
GetVertex(index[j], vj);
|
||
vj.nx = sum.x;
|
||
vj.ny = sum.y;
|
||
vj.nz = sum.z;
|
||
SetVertex(index[j], vj);
|
||
}
|
||
}
|
||
|
||
free(bDone);
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
|
||
// Cast normals selected triangles.
|
||
|
||
void CModel::PlaneSelect()
|
||
{
|
||
Math::Vector p1, p2, p3, n;
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bSelect )
|
||
{
|
||
p1.x = m_triangleTable[i].p1.x;
|
||
p1.y = m_triangleTable[i].p1.y;
|
||
p1.z = m_triangleTable[i].p1.z;
|
||
|
||
p2.x = m_triangleTable[i].p2.x;
|
||
p2.y = m_triangleTable[i].p2.y;
|
||
p2.z = m_triangleTable[i].p2.z;
|
||
|
||
p3.x = m_triangleTable[i].p3.x;
|
||
p3.y = m_triangleTable[i].p3.y;
|
||
p3.z = m_triangleTable[i].p3.z;
|
||
|
||
n = Math::NormalToPlane(p3, p2, p1);
|
||
|
||
m_triangleTable[i].p3.nx = n.x;
|
||
m_triangleTable[i].p3.ny = n.y;
|
||
m_triangleTable[i].p3.nz = n.z;
|
||
}
|
||
}
|
||
SelectTerm();
|
||
}
|
||
|
||
|
||
// Change the color of the selected triangles.
|
||
|
||
void CModel::ColorSelect()
|
||
{
|
||
int used, i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bSelect )
|
||
{
|
||
m_triangleTable[i].material.diffuse.r = table_color[m_color*3+0];
|
||
m_triangleTable[i].material.diffuse.g = table_color[m_color*3+1];
|
||
m_triangleTable[i].material.diffuse.b = table_color[m_color*3+2];
|
||
}
|
||
}
|
||
SelectTerm();
|
||
}
|
||
|
||
// Change the status of selected triangles.
|
||
|
||
void CModel::StateSelect()
|
||
{
|
||
int used, i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bSelect )
|
||
{
|
||
m_triangleTable[i].state = table_state[m_state];
|
||
}
|
||
}
|
||
SelectTerm();
|
||
}
|
||
|
||
// Moves the selection.
|
||
|
||
void CModel::MoveSelect(Math::Vector move)
|
||
{
|
||
if ( m_oper == 'Z' )
|
||
{
|
||
if ( move.x == +1 ) move.x = 1.1f;
|
||
else if ( move.x == -1 ) move.x = 1.0f/1.1f;
|
||
else move.x = 1.0f;
|
||
if ( move.y == +1 ) move.y = 1.1f;
|
||
else if ( move.y == -1 ) move.y = 1.0f/1.1f;
|
||
else move.y = 1.0f;
|
||
if ( move.z == +1 ) move.z = 1.1f;
|
||
else if ( move.z == -1 ) move.z = 1.0f/1.1f;
|
||
else move.z = 1.0f;
|
||
}
|
||
if ( m_oper == 'R' )
|
||
{
|
||
#if 0
|
||
if ( move.x == +1 ) move.x = 5.0f*Math::PI/180.0f;
|
||
else if ( move.x == -1 ) move.x = -5.0f*Math::PI/180.0f;
|
||
if ( move.y == +1 ) move.y = 5.0f*Math::PI/180.0f;
|
||
else if ( move.y == -1 ) move.y = -5.0f*Math::PI/180.0f;
|
||
if ( move.z == +1 ) move.z = 5.0f*Math::PI/180.0f;
|
||
else if ( move.z == -1 ) move.z = -5.0f*Math::PI/180.0f;
|
||
#else
|
||
if ( move.x == +1 ) move.x = 45.0f*Math::PI/180.0f;
|
||
else if ( move.x == -1 ) move.x = -45.0f*Math::PI/180.0f;
|
||
if ( move.y == +1 ) move.y = 45.0f*Math::PI/180.0f;
|
||
else if ( move.y == -1 ) move.y = -45.0f*Math::PI/180.0f;
|
||
if ( move.z == +1 ) move.z = 45.0f*Math::PI/180.0f;
|
||
else if ( move.z == -1 ) move.z = -45.0f*Math::PI/180.0f;
|
||
#endif
|
||
}
|
||
|
||
OperSelect(move, m_oper);
|
||
}
|
||
|
||
// Moves the selection.
|
||
|
||
void CModel::OperSelect(Math::Vector move, char oper)
|
||
{
|
||
Math::Point rot;
|
||
int used, i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bSelect )
|
||
{
|
||
if ( oper == 'P' )
|
||
{
|
||
m_triangleTable[i].p1.x += move.x;
|
||
m_triangleTable[i].p1.y += move.y;
|
||
m_triangleTable[i].p1.z += move.z;
|
||
m_triangleTable[i].p2.x += move.x;
|
||
m_triangleTable[i].p2.y += move.y;
|
||
m_triangleTable[i].p2.z += move.z;
|
||
m_triangleTable[i].p3.x += move.x;
|
||
m_triangleTable[i].p3.y += move.y;
|
||
m_triangleTable[i].p3.z += move.z;
|
||
}
|
||
if ( oper == 'Z' )
|
||
{
|
||
m_triangleTable[i].p1.x *= move.x;
|
||
m_triangleTable[i].p1.y *= move.y;
|
||
m_triangleTable[i].p1.z *= move.z;
|
||
m_triangleTable[i].p2.x *= move.x;
|
||
m_triangleTable[i].p2.y *= move.y;
|
||
m_triangleTable[i].p2.z *= move.z;
|
||
m_triangleTable[i].p3.x *= move.x;
|
||
m_triangleTable[i].p3.y *= move.y;
|
||
m_triangleTable[i].p3.z *= move.z;
|
||
}
|
||
if ( oper == 'R' )
|
||
{
|
||
if ( move.x != 0 )
|
||
{
|
||
rot.x = m_triangleTable[i].p1.z;
|
||
rot.y = m_triangleTable[i].p1.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
|
||
m_triangleTable[i].p1.z = rot.x;
|
||
m_triangleTable[i].p1.y = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p2.z;
|
||
rot.y = m_triangleTable[i].p2.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
|
||
m_triangleTable[i].p2.z = rot.x;
|
||
m_triangleTable[i].p2.y = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p3.z;
|
||
rot.y = m_triangleTable[i].p3.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
|
||
m_triangleTable[i].p3.z = rot.x;
|
||
m_triangleTable[i].p3.y = rot.y;
|
||
}
|
||
if ( move.y != 0 )
|
||
{
|
||
rot.x = m_triangleTable[i].p1.x;
|
||
rot.y = m_triangleTable[i].p1.z;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
|
||
m_triangleTable[i].p1.x = rot.x;
|
||
m_triangleTable[i].p1.z = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p2.x;
|
||
rot.y = m_triangleTable[i].p2.z;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
|
||
m_triangleTable[i].p2.x = rot.x;
|
||
m_triangleTable[i].p2.z = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p3.x;
|
||
rot.y = m_triangleTable[i].p3.z;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
|
||
m_triangleTable[i].p3.x = rot.x;
|
||
m_triangleTable[i].p3.z = rot.y;
|
||
}
|
||
if ( move.z != 0 )
|
||
{
|
||
rot.x = m_triangleTable[i].p1.x;
|
||
rot.y = m_triangleTable[i].p1.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
|
||
m_triangleTable[i].p1.x = rot.x;
|
||
m_triangleTable[i].p1.y = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p2.x;
|
||
rot.y = m_triangleTable[i].p2.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
|
||
m_triangleTable[i].p2.x = rot.x;
|
||
m_triangleTable[i].p2.y = rot.y;
|
||
|
||
rot.x = m_triangleTable[i].p3.x;
|
||
rot.y = m_triangleTable[i].p3.y;
|
||
rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
|
||
m_triangleTable[i].p3.x = rot.x;
|
||
m_triangleTable[i].p3.y = rot.y;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
SelectTerm();
|
||
}
|
||
|
||
// Performs a build script.
|
||
|
||
void CModel::ReadScript(char *filename)
|
||
{
|
||
FILE* file = NULL;
|
||
char line[200];
|
||
char name[200];
|
||
char buffer[200];
|
||
int i, first, last;
|
||
Math::Vector move;
|
||
bool bFirst = true;
|
||
|
||
file = fopen(filename, "r");
|
||
if ( file == NULL ) return;
|
||
|
||
while ( fgets(line, 200, file) != NULL )
|
||
{
|
||
for ( i=0 ; i<200 ; i++ )
|
||
{
|
||
if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
|
||
if ( line[i] == '/' && line[i+1] == '/' )
|
||
{
|
||
line[i] = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( Cmd(line, "Object") )
|
||
{
|
||
OpString(line, "name", name);
|
||
sprintf(buffer, "objects\\%s.mod", name);
|
||
|
||
if ( bFirst )
|
||
{
|
||
m_modFile->ReadModel(buffer, true, true);
|
||
last = m_modFile->RetTriangleUsed();
|
||
SelectZone(0, last);
|
||
}
|
||
else
|
||
{
|
||
first = m_modFile->RetTriangleUsed();
|
||
m_modFile->AddModel(buffer, first, true, false);
|
||
last = m_modFile->RetTriangleUsed();
|
||
SelectZone(first, last);
|
||
}
|
||
bFirst = false;
|
||
|
||
move = OpDir(line, "zoom");
|
||
OperSelect(move, 'Z');
|
||
|
||
move = OpDir(line, "rot");
|
||
move *= Math::PI/180.0f; // degrees -> radians
|
||
OperSelect(move, 'R');
|
||
|
||
move = OpDir(line, "pos");
|
||
OperSelect(move, 'P');
|
||
}
|
||
}
|
||
|
||
fclose(file);
|
||
}
|
||
|
||
|
||
|
||
// Computes the bbox of selected triangles.
|
||
|
||
void CModel::BBoxCompute(Math::Vector &min, Math::Vector &max)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
int used, i;
|
||
|
||
min.x = 1000000.0f;
|
||
min.y = 1000000.0f;
|
||
min.z = 1000000.0f;
|
||
max.x = -1000000.0f;
|
||
max.y = -1000000.0f;
|
||
max.z = -1000000.0f;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
if ( vertex.x < min.x ) min.x = vertex.x;
|
||
if ( vertex.y < min.y ) min.y = vertex.y;
|
||
if ( vertex.z < min.z ) min.z = vertex.z;
|
||
|
||
if ( vertex.x > max.x ) max.x = vertex.x;
|
||
if ( vertex.y > max.y ) max.y = vertex.y;
|
||
if ( vertex.z > max.z ) max.z = vertex.z;
|
||
}
|
||
}
|
||
|
||
// Returns the gravity center of the selection.
|
||
|
||
Math::Vector CModel::RetSelectCDG()
|
||
{
|
||
Math::Vector min, max, cdg;
|
||
|
||
BBoxCompute(min, max);
|
||
|
||
cdg.x = (min.x+max.x)/2.0f;
|
||
cdg.y = (min.y+max.y)/2.0f;
|
||
cdg.z = (min.z+max.z)/2.0f;
|
||
|
||
return cdg;
|
||
}
|
||
|
||
// Returns the normal vector of the selection.
|
||
|
||
Math::Vector CModel::RetSelectNormal()
|
||
{
|
||
Math::Vector p1, p2, p3, n;
|
||
|
||
p1.x = m_triangleTable[m_triangleSel1].p1.nx;
|
||
p1.y = m_triangleTable[m_triangleSel1].p1.ny;
|
||
p1.z = m_triangleTable[m_triangleSel1].p1.nz;
|
||
|
||
p2.x = m_triangleTable[m_triangleSel1].p2.nx;
|
||
p2.y = m_triangleTable[m_triangleSel1].p2.ny;
|
||
p2.z = m_triangleTable[m_triangleSel1].p2.nz;
|
||
|
||
p3.x = m_triangleTable[m_triangleSel1].p3.nx;
|
||
p3.y = m_triangleTable[m_triangleSel1].p3.ny;
|
||
p3.z = m_triangleTable[m_triangleSel1].p3.nz;
|
||
|
||
n = Normalize(p1+p2+p3);
|
||
|
||
return n;
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
bool CModel::IsMappingSelectPlausible(D3DMaping D3Dmode)
|
||
{
|
||
D3DVERTEX2 vertex[3];
|
||
Math::Vector min, max;
|
||
Math::Point a, b, ti, ts;
|
||
float au, bu, av, bv;
|
||
int used, i, j;
|
||
|
||
ti.x = 0.0f;
|
||
ti.y = 0.0f;
|
||
ts.x = 1.0f;
|
||
ts.y = 1.0f;
|
||
|
||
BBoxCompute(min, max);
|
||
|
||
if ( D3Dmode == D3DMAPPINGX )
|
||
{
|
||
a.x = min.z;
|
||
a.y = min.y;
|
||
b.x = max.z;
|
||
b.y = max.y;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGY )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.z;
|
||
b.x = max.x;
|
||
b.y = max.z;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGZ )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.y;
|
||
b.x = max.x;
|
||
b.y = max.y;
|
||
}
|
||
|
||
au = (ts.x-ti.x)/(b.x-a.x);
|
||
bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
|
||
|
||
av = (ts.y-ti.y)/(b.y-a.y);
|
||
bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( !GetVertex(i*3+0, vertex[0]) ) continue;
|
||
if ( !GetVertex(i*3+1, vertex[1]) ) continue;
|
||
if ( !GetVertex(i*3+2, vertex[2]) ) continue;
|
||
|
||
for ( j=0 ; j<3 ; j++ )
|
||
{
|
||
if ( D3Dmode == D3DMAPPINGX )
|
||
{
|
||
vertex[j].tu = vertex[j].z*au+bu;
|
||
vertex[j].tv = vertex[j].y*av+bv;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGY )
|
||
{
|
||
vertex[j].tu = vertex[j].x*au+bu;
|
||
vertex[j].tv = vertex[j].z*av+bv;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGZ )
|
||
{
|
||
vertex[j].tu = vertex[j].x*au+bu;
|
||
vertex[j].tv = vertex[j].y*av+bv;
|
||
}
|
||
}
|
||
|
||
if ( vertex[0].tu == vertex[1].tu &&
|
||
vertex[0].tu == vertex[2].tu ) return false;
|
||
|
||
if ( vertex[0].tv == vertex[1].tv &&
|
||
vertex[0].tv == vertex[2].tv ) return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY,
|
||
Math::Point ti, Math::Point ts, char *texName)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max;
|
||
Math::Point a, b;
|
||
D3DMaping D3Dmode;
|
||
float au, bu, av, bv;
|
||
int used, i;
|
||
bool bPlausible[3];
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( !m_triangleTable[i].bUsed ) continue;
|
||
if ( !m_triangleTable[i].bSelect ) continue;
|
||
|
||
strcpy(m_triangleTable[i].texName, texName);
|
||
}
|
||
|
||
if ( mode == 1 )
|
||
{
|
||
MappingSelectSpherical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
|
||
return;
|
||
}
|
||
if ( mode == 2 )
|
||
{
|
||
MappingSelectCylindrical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
|
||
return;
|
||
}
|
||
if ( mode == 3 )
|
||
{
|
||
MappingSelectFace(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
|
||
return;
|
||
}
|
||
|
||
BBoxCompute(min, max);
|
||
|
||
bPlausible[0] = IsMappingSelectPlausible(D3DMAPPINGX);
|
||
bPlausible[1] = IsMappingSelectPlausible(D3DMAPPINGY);
|
||
bPlausible[2] = IsMappingSelectPlausible(D3DMAPPINGZ);
|
||
|
||
for ( i=0 ; i<9 ; i++ )
|
||
{
|
||
if ( !bPlausible[i%3] ) continue;
|
||
if ( rotate-- == 0 ) break;
|
||
}
|
||
if ( i%3 == 0 ) D3Dmode = D3DMAPPINGX;
|
||
if ( i%3 == 1 ) D3Dmode = D3DMAPPINGY;
|
||
if ( i%3 == 2 ) D3Dmode = D3DMAPPINGZ;
|
||
|
||
if ( D3Dmode == D3DMAPPINGX )
|
||
{
|
||
a.x = min.z;
|
||
a.y = min.y;
|
||
b.x = max.z;
|
||
b.y = max.y;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGY )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.z;
|
||
b.x = max.x;
|
||
b.y = max.z;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGZ )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.y;
|
||
b.x = max.x;
|
||
b.y = max.y;
|
||
}
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
au = (ts.x-ti.x)/(b.x-a.x);
|
||
bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
|
||
|
||
av = (ts.y-ti.y)/(b.y-a.y);
|
||
bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
|
||
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
if ( D3Dmode == D3DMAPPINGX )
|
||
{
|
||
vertex.tu = vertex.z*au+bu;
|
||
vertex.tv = vertex.y*av+bv;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGY )
|
||
{
|
||
vertex.tu = vertex.x*au+bu;
|
||
vertex.tv = vertex.z*av+bv;
|
||
}
|
||
if ( D3Dmode == D3DMAPPINGZ )
|
||
{
|
||
vertex.tu = vertex.x*au+bu;
|
||
vertex.tv = vertex.y*av+bv;
|
||
}
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
|
||
Math::Point ti, Math::Point ts, char *texName)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max, center, dim, p;
|
||
float radius, k, u, v;
|
||
int used, i;
|
||
|
||
BBoxCompute(min, max);
|
||
center = (min+max)/2.0f;
|
||
dim = (max-min)/2.0f;
|
||
radius = Math::Min(dim.x, dim.y, dim.z);
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
p.x = vertex.x-center.x;
|
||
p.y = vertex.y-center.y;
|
||
p.z = vertex.z-center.z;
|
||
|
||
k = radius/p.Length();
|
||
u = k*p.x;
|
||
v = k*p.z;
|
||
u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
|
||
v = (v/dim.z*2.0f+1.0f)/2.0f;
|
||
|
||
vertex.tu = ti.x+(ts.x-ti.x)*u;
|
||
vertex.tv = ti.y+(ts.y-ti.y)*v;
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
// Seeking the center of a group of points.
|
||
|
||
Math::Vector CModel::RetMappingCenter(Math::Vector pos, Math::Vector min)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector center, p;
|
||
int used, i, nb;
|
||
|
||
center.x = 0.0f;
|
||
center.y = 0.0f;
|
||
center.z = 0.0f;
|
||
|
||
nb = 0;
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
p.x = vertex.x;
|
||
p.y = vertex.y;
|
||
p.z = vertex.z;
|
||
|
||
if ( fabs(p.x-pos.x) <= min.x &&
|
||
fabs(p.y-pos.y) <= min.y &&
|
||
fabs(p.z-pos.z) <= min.z )
|
||
{
|
||
center.x += p.x;
|
||
center.y += p.y;
|
||
center.z += p.z;
|
||
nb ++;
|
||
}
|
||
}
|
||
|
||
if ( nb == 0 ) return pos;
|
||
|
||
center.x /= (float)nb;
|
||
center.y /= (float)nb;
|
||
center.z /= (float)nb;
|
||
|
||
return center;
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
|
||
Math::Point ti, Math::Point ts, char *texName)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max, center, local, dim, p, pp, box;
|
||
float radius, u, v;
|
||
int used, i;
|
||
|
||
BBoxCompute(min, max);
|
||
center = (min+max)/2.0f;
|
||
dim = (max-min)/2.0f;
|
||
radius = Math::Min(dim.x, dim.y, dim.z);
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
if ( rotate == 0 )
|
||
{
|
||
box.x = 2.0f;
|
||
box.y = 10.0f;
|
||
box.z = 10.0f;
|
||
}
|
||
if ( rotate == 1 )
|
||
{
|
||
box.x = 10.0f;
|
||
box.y = 2.0f;
|
||
box.z = 10.0f;
|
||
}
|
||
if ( rotate == 2 )
|
||
{
|
||
box.x = 10.0f;
|
||
box.y = 10.0f;
|
||
box.z = 2.0f;
|
||
}
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
p.x = vertex.x;
|
||
p.y = vertex.y;
|
||
p.z = vertex.z;
|
||
|
||
#if 1
|
||
p.x -= center.x;
|
||
p.y -= center.y;
|
||
p.z -= center.z;
|
||
|
||
pp = p;
|
||
#else
|
||
local = RetMappingCenter(p, box);
|
||
|
||
pp = p;
|
||
pp.x -= local.x;
|
||
pp.y -= local.y;
|
||
pp.z -= local.z;
|
||
|
||
p.x -= center.x;
|
||
p.y -= center.y;
|
||
p.z -= center.z;
|
||
#endif
|
||
|
||
if ( rotate == 0 )
|
||
{
|
||
u = Math::RotateAngle(pp.y, pp.z);
|
||
v = p.x/dim.x/2.0f + 0.5f;
|
||
}
|
||
if ( rotate == 1 )
|
||
{
|
||
u = Math::RotateAngle(pp.x, pp.z);
|
||
v = p.y/dim.y/2.0f + 0.5f;
|
||
}
|
||
if ( rotate == 2 )
|
||
{
|
||
u = Math::RotateAngle(pp.x, pp.y);
|
||
v = p.z/dim.z/2.0f + 0.5f;
|
||
}
|
||
|
||
//? if ( u < Math::PI ) u = u/Math::PI;
|
||
//? else u = 2.0f-u/Math::PI;
|
||
u = u/(Math::PI*2.0f);
|
||
|
||
vertex.tu = ti.x+(ts.x-ti.x)*u;
|
||
vertex.tv = ti.y+(ts.y-ti.y)*v;
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY,
|
||
Math::Point ti, Math::Point ts, char *texName)
|
||
{
|
||
D3DVERTEX2 vertex[3];
|
||
Math::Vector min, max, center, local, dim, p;
|
||
float radius, u[3], v[3], m[3], avg;
|
||
int used, i, j;
|
||
|
||
BBoxCompute(min, max);
|
||
center = (min+max)/2.0f;
|
||
dim = (max-min)/2.0f;
|
||
radius = Math::Min(dim.x, dim.y, dim.z);
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
for ( j=0 ; j<3 ; j++ )
|
||
{
|
||
if ( !GetVertex(i*3+j, vertex[j]) ) continue;
|
||
|
||
p.x = vertex[j].x - center.x;
|
||
p.y = vertex[j].y - center.y;
|
||
p.z = vertex[j].z - center.z;
|
||
|
||
#if 0
|
||
u[j] = Math::RotateAngle(p.x, p.z)/(Math::PI*2.0f)+0.5f;
|
||
if ( u[j] > 1.0f ) u[j] -= 1.0f;
|
||
#else
|
||
u[j] = Math::RotateAngle(p.x, p.z)/Math::PI;
|
||
//? if ( u[j] > 1.0f ) u[j] = 2.0f-u[j];
|
||
if ( u[j] > 1.0f ) u[j] -= 1.0f;
|
||
#endif
|
||
|
||
v[j] = p.y/dim.y/2.0f + 0.5f;
|
||
|
||
if ( u[j] < 0.5f ) m[j] = u[j];
|
||
else m[j] = u[j]-1.0f;
|
||
}
|
||
|
||
avg = (m[0]+m[1]+m[2])/3.0f;
|
||
|
||
for ( j=0 ; j<3 ; j++ )
|
||
{
|
||
if ( u[j] < 0.05f || u[j] > 0.95f )
|
||
{
|
||
if ( avg > 0.0f ) u[j] = 0.0f;
|
||
else u[j] = 1.0f;
|
||
}
|
||
|
||
vertex[j].tu = ti.x+(ts.x-ti.x)*u[j];
|
||
vertex[j].tv = ti.y+(ts.y-ti.y)*v[j];
|
||
|
||
SetVertex(i*3+j, vertex[j]);
|
||
}
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
|
||
// Maps a secondary texture on selected triangles.
|
||
|
||
void CModel::MappingSelect2(int texNum2, int subdiv,
|
||
int offsetU, int offsetV,
|
||
bool bMirrorX, bool bMirrorY)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max, center, p;
|
||
float u ,v;
|
||
int used, i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( !m_triangleTable[i].bUsed ) continue;
|
||
if ( !m_triangleTable[i].bSelect ) continue;
|
||
|
||
m_triangleTable[i].texNum2 = texNum2;
|
||
}
|
||
|
||
if ( subdiv == 6 )
|
||
{
|
||
MappingSelectSpherical2(bMirrorX, bMirrorY);
|
||
return;
|
||
}
|
||
if ( subdiv == 7 )
|
||
{
|
||
MappingSelectMagic2(bMirrorX, bMirrorY);
|
||
return;
|
||
}
|
||
if ( subdiv > 2 )
|
||
{
|
||
MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY);
|
||
return;
|
||
}
|
||
|
||
BBoxCompute(min, max);
|
||
center = (min+max)/2.0f;
|
||
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
p.x = vertex.x-center.x;
|
||
p.y = vertex.y-center.y;
|
||
p.z = vertex.z-center.z;
|
||
|
||
u = Math::RotateAngle(p.x, p.z);
|
||
v = Math::RotateAngle(Math::Point(p.x, p.z).Length(), p.y);
|
||
if ( p.x < 0.0f ) v += Math::PI;
|
||
|
||
u = Math::NormAngle(u+(float)offsetU*Math::PI/180.0f);
|
||
v = Math::NormAngle(v+(float)offsetV*Math::PI/180.0f);
|
||
|
||
if ( subdiv == 1 )
|
||
{
|
||
u = u/(Math::PI*2.0f);
|
||
v = v/(Math::PI*2.0f);
|
||
}
|
||
if ( subdiv == 2 )
|
||
{
|
||
if ( u < Math::PI ) u = u/Math::PI;
|
||
else u = (Math::PI*2.0f-u)/Math::PI;
|
||
if ( v < Math::PI ) v = v/Math::PI;
|
||
else v = (Math::PI*2.0f-v)/Math::PI;
|
||
}
|
||
|
||
vertex.tu2 = u;
|
||
vertex.tv2 = v;
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
// Maps a secondary texture on flat.
|
||
|
||
void CModel::MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max;
|
||
Math::Point ti, ts, a, b;
|
||
float au, bu, av, bv;
|
||
int used, i;
|
||
|
||
ti = Math::Point(0.0f, 0.0f);
|
||
ts = Math::Point(1.0f, 1.0f);
|
||
|
||
BBoxCompute(min, max);
|
||
|
||
if ( mode == 0 )
|
||
{
|
||
a.x = min.z;
|
||
a.y = min.y;
|
||
b.x = max.z;
|
||
b.y = max.y;
|
||
}
|
||
if ( mode == 1 )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.z;
|
||
b.x = max.x;
|
||
b.y = max.z;
|
||
}
|
||
if ( mode == 2 )
|
||
{
|
||
a.x = min.x;
|
||
a.y = min.y;
|
||
b.x = max.x;
|
||
b.y = max.y;
|
||
}
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
au = (ts.x-ti.x)/(b.x-a.x);
|
||
bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
|
||
|
||
av = (ts.y-ti.y)/(b.y-a.y);
|
||
bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
if ( mode == 0 )
|
||
{
|
||
vertex.tu2 = vertex.z*au+bu;
|
||
vertex.tv2 = vertex.y*av+bv;
|
||
}
|
||
if ( mode == 1 )
|
||
{
|
||
vertex.tu2 = vertex.x*au+bu;
|
||
vertex.tv2 = vertex.z*av+bv;
|
||
}
|
||
if ( mode == 2 )
|
||
{
|
||
vertex.tu2 = vertex.x*au+bu;
|
||
vertex.tv2 = vertex.y*av+bv;
|
||
}
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelectSpherical2(bool bMirrorX, bool bMirrorY)
|
||
{
|
||
D3DVERTEX2 vertex;
|
||
Math::Vector min, max, center, dim, p;
|
||
Math::Point ti, ts;
|
||
float radius, k, u, v;
|
||
int used, i;
|
||
|
||
BBoxCompute(min, max);
|
||
center = (min+max)/2.0f;
|
||
dim = (max-min)/2.0f;
|
||
radius = Math::Min(dim.x, dim.y, dim.z);
|
||
|
||
ti = Math::Point(0.0f, 0.0f);
|
||
ts = Math::Point(1.0f, 1.0f);
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
p.x = vertex.x-center.x;
|
||
p.y = vertex.y-center.y;
|
||
p.z = vertex.z-center.z;
|
||
|
||
k = radius/p.Length();
|
||
u = k*p.x;
|
||
v = k*p.z;
|
||
u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
|
||
v = (v/dim.z*2.0f+1.0f)/2.0f;
|
||
|
||
vertex.tu2 = ti.x+(ts.x-ti.x)*u;
|
||
vertex.tv2 = ti.y+(ts.y-ti.y)*v;
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
// Maps a texture onto the selected triangles.
|
||
|
||
void CModel::MappingSelectMagic2(bool bMirrorX, bool bMirrorY)
|
||
{
|
||
D3DVERTEX2 vertex, v[3];
|
||
Math::Vector min, max, au, bu, av, bv, n;
|
||
Math::Point ti, ts;
|
||
int used, i, mode;
|
||
|
||
ti = Math::Point(0.0f, 0.0f);
|
||
ts = Math::Point(1.0f, 1.0f);
|
||
|
||
BBoxCompute(min, max);
|
||
|
||
if ( bMirrorX )
|
||
{
|
||
Math::Swap(ti.x, ts.x);
|
||
}
|
||
|
||
if ( !bMirrorY ) // reverse test!
|
||
{
|
||
Math::Swap(ti.y, ts.y);
|
||
}
|
||
|
||
au.x = (ts.x-ti.x)/(max.x-min.x);
|
||
bu.x = ts.x-max.x*(ts.x-ti.x)/(max.x-min.x);
|
||
au.y = (ts.x-ti.x)/(max.y-min.y);
|
||
bu.y = ts.x-max.y*(ts.x-ti.x)/(max.y-min.y);
|
||
au.z = (ts.x-ti.x)/(max.z-min.z);
|
||
bu.z = ts.x-max.z*(ts.x-ti.x)/(max.z-min.z);
|
||
|
||
av.x = (ts.y-ti.y)/(max.x-min.x);
|
||
bv.x = ts.y-max.x*(ts.y-ti.y)/(max.x-min.x);
|
||
av.y = (ts.y-ti.y)/(max.y-min.y);
|
||
bv.y = ts.y-max.y*(ts.y-ti.y)/(max.y-min.y);
|
||
av.z = (ts.y-ti.y)/(max.z-min.z);
|
||
bv.z = ts.y-max.z*(ts.y-ti.y)/(max.z-min.z);
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used*3 ; i++ )
|
||
{
|
||
if ( i%3 == 0 )
|
||
{
|
||
if ( !GetVertex(i+0, v[0]) ) continue;
|
||
if ( !GetVertex(i+1, v[1]) ) continue;
|
||
if ( !GetVertex(i+2, v[2]) ) continue;
|
||
|
||
n = Math::NormalToPlane(Math::Vector(v[0].x, v[0].y, v[0].z),
|
||
Math::Vector(v[1].x, v[1].y, v[1].z),
|
||
Math::Vector(v[2].x, v[2].y, v[2].z));
|
||
|
||
n.x = fabs(n.x);
|
||
n.y = fabs(n.y);
|
||
n.z = fabs(n.z);
|
||
|
||
if ( n.x >= Math::Max(n.y, n.z) ) mode = 0;
|
||
if ( n.y >= Math::Max(n.x, n.z) ) mode = 1;
|
||
if ( n.z >= Math::Max(n.x, n.y) ) mode = 2;
|
||
}
|
||
|
||
if ( !GetVertex(i, vertex) ) continue;
|
||
|
||
if ( mode == 0 )
|
||
{
|
||
vertex.tu2 = vertex.z*au.z+bu.z;
|
||
vertex.tv2 = vertex.y*av.y+bv.y;
|
||
}
|
||
if ( mode == 1 )
|
||
{
|
||
vertex.tu2 = vertex.x*au.x+bu.x;
|
||
vertex.tv2 = vertex.z*av.z+bv.z;
|
||
}
|
||
if ( mode == 2 )
|
||
{
|
||
vertex.tu2 = vertex.x*au.x+bu.x;
|
||
vertex.tv2 = vertex.y*av.y+bv.y;
|
||
}
|
||
|
||
SetVertex(i, vertex);
|
||
}
|
||
|
||
SelectTerm();
|
||
}
|
||
|
||
|
||
// Seeks the next triangle.
|
||
|
||
int CModel::SearchNext(int rank, int step)
|
||
{
|
||
int max, i;
|
||
|
||
max = m_modFile->RetTriangleUsed();
|
||
|
||
for ( i=0 ; i<max ; i++ )
|
||
{
|
||
rank += step;
|
||
if ( rank < 0 ) rank = max-1;
|
||
if ( rank >= max ) rank = 0;
|
||
|
||
if ( m_triangleTable[rank].min != m_min ||
|
||
m_triangleTable[rank].max != m_max ) continue;
|
||
|
||
if ( m_triangleTable[rank].bUsed ) break;
|
||
}
|
||
return rank;
|
||
}
|
||
|
||
// Seeks all the triangles belonging to the same plane.
|
||
|
||
int CModel::SearchSamePlane(int first, int step)
|
||
{
|
||
Math::Vector vFirst[3], vNext[3];
|
||
int last, i;
|
||
|
||
vFirst[0].x = m_triangleTable[first].p1.x;
|
||
vFirst[0].y = m_triangleTable[first].p1.y;
|
||
vFirst[0].z = m_triangleTable[first].p1.z;
|
||
vFirst[1].x = m_triangleTable[first].p2.x;
|
||
vFirst[1].y = m_triangleTable[first].p2.y;
|
||
vFirst[1].z = m_triangleTable[first].p2.z;
|
||
vFirst[2].x = m_triangleTable[first].p3.x;
|
||
vFirst[2].y = m_triangleTable[first].p3.y;
|
||
vFirst[2].z = m_triangleTable[first].p3.z;
|
||
|
||
for ( i=0 ; i<1000 ; i++ )
|
||
{
|
||
last = first;
|
||
first = SearchNext(first, step);
|
||
|
||
vNext[0].x = m_triangleTable[first].p1.x;
|
||
vNext[0].y = m_triangleTable[first].p1.y;
|
||
vNext[0].z = m_triangleTable[first].p1.z;
|
||
vNext[1].x = m_triangleTable[first].p2.x;
|
||
vNext[1].y = m_triangleTable[first].p2.y;
|
||
vNext[1].z = m_triangleTable[first].p2.z;
|
||
vNext[2].x = m_triangleTable[first].p3.x;
|
||
vNext[2].y = m_triangleTable[first].p3.y;
|
||
vNext[2].z = m_triangleTable[first].p3.z;
|
||
|
||
if ( !IsSamePlane(vFirst, vNext) ) // other plan?
|
||
{
|
||
return last;
|
||
}
|
||
}
|
||
return first;
|
||
}
|
||
|
||
// Seeks the next triangle.
|
||
|
||
void CModel::CurrentSearchNext(int step, bool bControl)
|
||
{
|
||
if ( step > 0 ) // forward?
|
||
{
|
||
m_triangleSel1 = SearchNext(m_triangleSel2, step);
|
||
if ( bControl )
|
||
{
|
||
m_triangleSel2 = m_triangleSel1;
|
||
}
|
||
else
|
||
{
|
||
m_triangleSel2 = SearchSamePlane(m_triangleSel1, step);
|
||
}
|
||
}
|
||
if ( step < 0 ) // back?
|
||
{
|
||
m_triangleSel2 = SearchNext(m_triangleSel1, step);
|
||
if ( bControl )
|
||
{
|
||
m_triangleSel1 = m_triangleSel2;
|
||
}
|
||
else
|
||
{
|
||
m_triangleSel1 = SearchSamePlane(m_triangleSel2, step);
|
||
}
|
||
}
|
||
|
||
#if 0
|
||
char s[100];
|
||
sprintf(s, "(%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f)",
|
||
m_triangleTable[m_triangleSel1].p1.x,
|
||
m_triangleTable[m_triangleSel1].p1.y,
|
||
m_triangleTable[m_triangleSel1].p1.z,
|
||
m_triangleTable[m_triangleSel1].p2.x,
|
||
m_triangleTable[m_triangleSel1].p2.y,
|
||
m_triangleTable[m_triangleSel1].p2.z,
|
||
m_triangleTable[m_triangleSel1].p3.x,
|
||
m_triangleTable[m_triangleSel1].p3.y,
|
||
m_triangleTable[m_triangleSel1].p3.z);
|
||
m_engine->SetInfoText(2, s);
|
||
sprintf(s, "(%.2f;%.2f) (%.2f;%.2f) (%.2f;%.2f)",
|
||
m_triangleTable[m_triangleSel1].p1.tu2,
|
||
m_triangleTable[m_triangleSel1].p1.tv2,
|
||
m_triangleTable[m_triangleSel1].p2.tu2,
|
||
m_triangleTable[m_triangleSel1].p2.tv2,
|
||
m_triangleTable[m_triangleSel1].p3.tu2,
|
||
m_triangleTable[m_triangleSel1].p3.tv2);
|
||
m_engine->SetInfoText(3, s);
|
||
#endif
|
||
|
||
InitViewFromSelect();
|
||
UpdateInfoText();
|
||
}
|
||
|
||
// Initializes the current triangles.
|
||
|
||
void CModel::CurrentInit()
|
||
{
|
||
m_triangleSel1 = 0;
|
||
m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
|
||
|
||
InitViewFromSelect();
|
||
UpdateInfoText();
|
||
}
|
||
|
||
// Selects the current triangles.
|
||
|
||
void CModel::CurrentSelect(bool bSelect)
|
||
{
|
||
int i;
|
||
|
||
for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
|
||
{
|
||
m_triangleTable[i].bSelect = bSelect;
|
||
}
|
||
}
|
||
|
||
|
||
// Deselects all triangles.
|
||
|
||
void CModel::DeselectAll()
|
||
{
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
m_triangleTable[i].bSelect = false;
|
||
}
|
||
}
|
||
|
||
// Selects an area.
|
||
|
||
void CModel::SelectZone(int first, int last)
|
||
{
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
m_triangleTable[i].bSelect = false;
|
||
if ( i >= first && i < last )
|
||
{
|
||
m_triangleTable[i].bSelect = true;
|
||
}
|
||
}
|
||
m_triangleSel1 = first;
|
||
m_triangleSel2 = last-1;
|
||
}
|
||
|
||
// Selects all triangles.
|
||
|
||
void CModel::SelectAll()
|
||
{
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].min == m_min &&
|
||
m_triangleTable[i].max == m_max )
|
||
{
|
||
m_triangleTable[i].bSelect = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Deselects all triangles.
|
||
|
||
void CModel::SelectTerm()
|
||
{
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( i >= m_triangleSel1 && i <= m_triangleSel2 )
|
||
{
|
||
if ( !m_triangleTable[i].bSelect ) return;
|
||
}
|
||
else
|
||
{
|
||
if ( m_triangleTable[i].bSelect ) return;
|
||
}
|
||
}
|
||
|
||
DeselectAll();
|
||
}
|
||
|
||
// Selects the triangles currents.
|
||
|
||
void CModel::DefaultSelect()
|
||
{
|
||
int used, i;
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
|
||
{
|
||
m_triangleTable[i].bSelect = true;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// Removes all selected triangles.
|
||
|
||
void CModel::SelectDelete()
|
||
{
|
||
int used ,i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bSelect )
|
||
{
|
||
m_triangleTable[i].bUsed = false;
|
||
}
|
||
}
|
||
|
||
i = m_triangleSel1;
|
||
Compress();
|
||
|
||
m_triangleSel1 = i;
|
||
m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
|
||
InitViewFromSelect();
|
||
UpdateInfoText();
|
||
}
|
||
|
||
// Compresses all triangles.
|
||
|
||
void CModel::Compress()
|
||
{
|
||
int used, i, j;
|
||
|
||
j = 0;
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( m_triangleTable[i].bUsed )
|
||
{
|
||
m_triangleTable[j++] = m_triangleTable[i];
|
||
}
|
||
}
|
||
m_modFile->SetTriangleUsed(j);
|
||
CurrentInit();
|
||
}
|
||
|
||
|
||
// Change the min / max of all selected triangles.
|
||
|
||
void CModel::MinMaxChange()
|
||
{
|
||
int used, i;
|
||
|
||
DefaultSelect();
|
||
|
||
used = m_modFile->RetTriangleUsed();
|
||
for ( i=0 ; i<used ; i++ )
|
||
{
|
||
if ( !m_triangleTable[i].bSelect ) continue;
|
||
|
||
m_triangleTable[i].min = m_min;
|
||
m_triangleTable[i].max = m_max;
|
||
}
|
||
}
|
||
|
||
|
||
// Initializes the point of view.
|
||
|
||
void CModel::InitView()
|
||
{
|
||
m_viewHeight = 5.0f;
|
||
m_viewDist = 50.0f;
|
||
m_viewAngleH = 0.0f;
|
||
m_viewAngleV = 0.0f;
|
||
}
|
||
|
||
// Initializes the point of view to see the selected triangles.
|
||
|
||
void CModel::InitViewFromSelect()
|
||
{
|
||
#if 0
|
||
Math::Vector n;
|
||
float h,v;
|
||
|
||
n = RetSelectNormal();
|
||
|
||
m_viewAngleH = Math::RotateAngle(n.x, n.z)+Math::PI;
|
||
m_viewAngleV = Math::RotateAngle(sqrtf(n.x*n.x+n.z*n.z), n.y)+Math::PI;
|
||
h = m_viewAngleH;
|
||
v = m_viewAngleV;
|
||
|
||
while ( m_viewAngleV <= -Math::PI )
|
||
{
|
||
m_viewAngleV += Math::PI;
|
||
m_viewAngleH += Math::PI;
|
||
}
|
||
while ( m_viewAngleV >= Math::PI )
|
||
{
|
||
m_viewAngleV -= Math::PI;
|
||
m_viewAngleH -= Math::PI;
|
||
}
|
||
m_viewAngleV *= 0.75f;
|
||
|
||
char s[100];
|
||
sprintf(s, "angle=%f %f -> %f %f\n", h,v, m_viewAngleH, m_viewAngleV);
|
||
OutputDebugString(s);
|
||
#endif
|
||
}
|
||
|
||
// Updates the parameters for the point of view.
|
||
|
||
void CModel::UpdateView()
|
||
{
|
||
Math::Vector eye, lookat, vUpVec;
|
||
|
||
//? lookat = RetSelectCDG();
|
||
lookat = Math::Vector(0.0f, m_viewHeight, 0.0f);
|
||
eye = RotateView(lookat, m_viewAngleH, m_viewAngleV, m_viewDist);
|
||
|
||
vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
|
||
m_engine->SetViewParams(eye, lookat, vUpVec, 10.0f);
|
||
m_engine->SetRankView(0);
|
||
}
|
||
|
||
// Moves the point of view.
|
||
|
||
void CModel::ViewMove(const Event &event, float speed)
|
||
{
|
||
if ( IsEditFocus() ) return;
|
||
|
||
// Up/Down.
|
||
if ( event.axeY > 0.5f )
|
||
{
|
||
if ( event.keyState & KS_CONTROL )
|
||
{
|
||
m_viewHeight += event.rTime*10.0f*speed;
|
||
if ( m_viewHeight > 100.0f ) m_viewHeight = 100.0f;
|
||
}
|
||
else
|
||
{
|
||
m_viewAngleV -= event.rTime*1.0f*speed;
|
||
if ( m_viewAngleV < -Math::PI*0.49f ) m_viewAngleV = -Math::PI*0.49f;
|
||
}
|
||
}
|
||
if ( event.axeY < -0.5f )
|
||
{
|
||
if ( event.keyState & KS_CONTROL )
|
||
{
|
||
m_viewHeight -= event.rTime*10.0f*speed;
|
||
if ( m_viewHeight < -100.0f ) m_viewHeight = -100.0f;
|
||
}
|
||
else
|
||
{
|
||
m_viewAngleV += event.rTime*1.0f*speed;
|
||
if ( m_viewAngleV > Math::PI*0.49f ) m_viewAngleV = Math::PI*0.49f;
|
||
}
|
||
}
|
||
|
||
// Left/Right.
|
||
if ( event.axeX < -0.5f )
|
||
{
|
||
m_viewAngleH -= event.rTime*1.0f*speed;
|
||
}
|
||
if ( event.axeX > 0.5f )
|
||
{
|
||
m_viewAngleH += event.rTime*1.0f*speed;
|
||
}
|
||
|
||
// PageUp/PageDown.
|
||
if ( event.keyState & KS_PAGEUP )
|
||
{
|
||
m_viewDist -= event.rTime*30.0f*speed;
|
||
if ( m_viewDist < 1.0f ) m_viewDist = 1.0f;
|
||
}
|
||
if ( event.keyState & KS_PAGEDOWN )
|
||
{
|
||
m_viewDist += event.rTime*30.0f*speed;
|
||
if ( m_viewDist > 300.0f ) m_viewDist = 300.0f;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// Updates the text information.
|
||
|
||
void CModel::UpdateInfoText()
|
||
{
|
||
char info[100];
|
||
|
||
if ( m_mode == 1 )
|
||
{
|
||
sprintf(info, "[1] V:color=%d K:state=%d Sel=%d..%d (T=%d)",
|
||
m_color, m_state,
|
||
m_triangleSel1, m_triangleSel2,
|
||
m_triangleSel2-m_triangleSel1+1);
|
||
m_engine->SetInfoText(0, info);
|
||
|
||
sprintf(info, "M:mode=%d Z:rot=%d XY:mir=%d;%d P:part=%d O:name=%s",
|
||
m_textureMode, m_textureRotate,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_texturePart, m_textureName);
|
||
m_engine->SetInfoText(1, info);
|
||
}
|
||
|
||
if ( m_mode == 2 )
|
||
{
|
||
sprintf(info, "[2] Sel=%d..%d (T=%d)",
|
||
m_triangleSel1, m_triangleSel2,
|
||
m_triangleSel2-m_triangleSel1+1);
|
||
m_engine->SetInfoText(0, info);
|
||
|
||
sprintf(info, "O:dirty=%d UV:offset=%d;%d XY:mir=%d;%d S:subdiv=%d",
|
||
m_secondTexNum,
|
||
m_secondOffsetU, m_secondOffsetV,
|
||
m_bTextureMirrorX, m_bTextureMirrorY,
|
||
m_secondSubdiv);
|
||
m_engine->SetInfoText(1, info);
|
||
}
|
||
|
||
if ( m_mode == 3 )
|
||
{
|
||
sprintf(info, "[3] LOD Math::Min/max=%d..%d Sel=%d..%d (T=%d)",
|
||
(int)m_min, (int)m_max,
|
||
m_triangleSel1, m_triangleSel2,
|
||
m_triangleSel2-m_triangleSel1+1);
|
||
m_engine->SetInfoText(0, info);
|
||
|
||
sprintf(info, "[Change]");
|
||
m_engine->SetInfoText(1, info);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
static int tablePartT[] = // lemt.tga
|
||
{
|
||
192, 0, 256, 32, // track profile
|
||
0, 64, 128, 128, // wheels for track
|
||
0, 0, 128, 64, // profile
|
||
90, 0, 128, 28, // pivot trainer
|
||
128, 0, 192, 44, // chest front
|
||
128, 44, 192, 58, // shell
|
||
128, 58, 192, 87, // back chest
|
||
128, 87, 192, 128, // back shell
|
||
128, 128, 192, 144, // sub back shell
|
||
0, 128, 32, 152, // rear fender
|
||
0, 152, 32, 182, // fender middle
|
||
0, 182, 32, 256, // front fender
|
||
32, 128, 112, 176, // wing
|
||
224, 48, 232, 64, // thrust tunnel
|
||
192, 32, 224, 64, // fire under reactor
|
||
224, 32, 256, 48, // foot
|
||
192, 64, 256, 128, // sensor
|
||
192, 128, 224, 176, // battery holder
|
||
192, 216, 248, 248, // cannon board
|
||
220, 216, 222, 245, // cannon board
|
||
64, 176, 128, 224, // top cannon
|
||
128, 152, 192, 160, // external cannon
|
||
128, 144, 192, 152, // interior cannon
|
||
192, 176, 224, 192, // small cannon
|
||
128, 236, 192, 256, // cannon organic
|
||
214, 192, 224, 216, // crosshair
|
||
224, 128, 248, 152, // articulation
|
||
128, 192, 192, 214, // piston board
|
||
128, 214, 192, 236, // piston front
|
||
192, 192, 214, 214, // piston edge
|
||
128, 192, 161, 214, // small piston board
|
||
32, 176, 64, 198, // radar piston
|
||
128, 160, 160, 192, // wheel
|
||
232, 48, 255, 56, // tire profile
|
||
240, 152, 248, 216, // vertical hatching
|
||
248, 192, 256, 256, // battery
|
||
224, 152, 240, 168, // rock
|
||
144, 80, 176, 112, // nuclear
|
||
140, 76, 180, 116, // large nuclear
|
||
144, 80, 152, 88, // yellow nuclear
|
||
224, 168, 240, 192, // cap resolution C
|
||
224, 192, 240, 210, // back resolution C
|
||
32, 224, 96, 235, // arm resolution C
|
||
32, 235, 96, 246, // arm resolution C
|
||
161, 1, 164, 4, // blank
|
||
168, 1, 171, 4, // medium gray
|
||
154, 1, 157, 4, // dark gray uniform
|
||
147, 1, 150, 4, // blue unifrom
|
||
114, 130, 118, 134, // red unifrom
|
||
121, 130, 125, 134, // green uniform
|
||
114, 137, 118, 141, // yellow uniform
|
||
121, 137, 125, 141, // violet uniform
|
||
-1
|
||
};
|
||
|
||
static int tablePartR[] = // roller.tga
|
||
{
|
||
0, 0, 128, 52, // wheels for track
|
||
48, 137, 128, 201, // catalytic radiator
|
||
0, 52, 32, 84, // front radiator
|
||
32, 52, 43, 84, // back radiator
|
||
0, 84, 96, 137, // large catalytic
|
||
128, 0, 192, 85, // front
|
||
128, 173, 192, 256, // back
|
||
192, 0, 256, 42, // over
|
||
128, 85, 192, 109, // catalytic pillon
|
||
128, 109, 192, 173, // top pillon
|
||
192, 85, 240, 109, // catalytic gate pillon
|
||
0, 137, 24, 256, // catalytic verrin
|
||
24, 137, 48, 256, // catalytic verrin
|
||
48, 201, 128, 233, // medium cannon
|
||
192, 109, 256, 173, // bottom cannon
|
||
192, 173, 240, 205, // cannon 1
|
||
192, 173, 240, 177, // cannon 2
|
||
43, 52, 75, 84, // front cannon
|
||
48, 233, 128, 247, // piston
|
||
96, 105, 128, 137, // front phazer
|
||
96, 97, 128, 105, // phazer cannon
|
||
75, 52, 107, 84, // exhaust pipe
|
||
192, 205, 243, 256, // nuclear power plant instruction
|
||
192, 42, 256, 85, // reflection glass
|
||
-1
|
||
};
|
||
|
||
static int tablePartW[] = // subm.tga
|
||
{
|
||
0, 0, 128, 26, // chenilles
|
||
0, 26, 22, 114, // portique 1
|
||
0, 114, 22, 202, // portique 2
|
||
22, 26, 82, 56, // c<>t<EFBFBD> hublot
|
||
22, 56, 82, 86, // c<>t<EFBFBD> ligne rouge
|
||
22, 86, 82, 116, // c<>t<EFBFBD> simple
|
||
22, 116, 82, 146, // avant/arri<72>re
|
||
22, 146, 82, 176, // avant/arri<72>re + phare
|
||
132, 82, 196, 166, // capot trainer
|
||
132, 166, 196, 177, // capot trainer
|
||
132, 177, 196, 188, // capot trainer
|
||
0, 224, 96, 256, // c<>t<EFBFBD> trainer
|
||
30, 224, 48, 256, // arri<72>re trainer
|
||
136, 240, 216, 256, // barri<72>re courte
|
||
96, 240, 256, 256, // barri<72>re longue
|
||
128, 0, 160, 32, // black-box 1
|
||
160, 0, 192, 32, // black-box 2
|
||
192, 0, 224, 32, // black-box 3
|
||
224, 105, 256, 137, // TNT 1
|
||
224, 137, 256, 169, // TNT 2
|
||
82, 32, 146, 82, // factory r<>solution C
|
||
146, 32, 210, 82, // factory r<>solution C
|
||
224, 0, 256, 105, // tower r<>solution C
|
||
82, 82, 132, 150, // research r<>solution C
|
||
199, 169, 256, 233, // sac r<>solution C
|
||
106, 150, 130, 214, // cl<63> A
|
||
82, 150, 106, 214, // cl<63> B
|
||
132, 188, 196, 212, // cl<63> C
|
||
132, 212, 196, 236, // cl<63> D
|
||
210, 32, 224, 46, // gris
|
||
56, 176, 82, 224, // sol coffre-fort
|
||
-1
|
||
};
|
||
|
||
static int tablePartDr[] = // drawer.tga
|
||
{
|
||
128, 0, 134, 6, // bleu
|
||
128, 6, 134, 12, // gris fonc<6E>
|
||
128, 12, 134, 18, // gris clair
|
||
0, 0, 128, 32, // roues chenille
|
||
192, 0, 256, 32, // profil chenille
|
||
140, 0, 160, 8, // profil phare
|
||
160, 0, 192, 32, // face phare
|
||
0, 32, 160, 48, // hachure
|
||
160, 32, 192, 48, // c<>t<EFBFBD>
|
||
0, 48, 96, 96, // tableau de bord
|
||
96, 48, 192, 112, // radiateur
|
||
192, 32, 256, 112, // grille lat<61>rale
|
||
192, 112, 256, 128, // capot
|
||
0, 96, 8, 160, // chassis
|
||
8, 96, 96, 104, // axe chenilles
|
||
8, 104, 16, 160, // axe carrousel
|
||
16, 128, 24, 160, // flan support
|
||
224, 128, 256, 160, // rotule
|
||
24, 104, 32, 160, // bocal (18)
|
||
32, 104, 40, 160, // bocal
|
||
40, 104, 48, 160, // bocal
|
||
24, 152, 48, 160, // bocal fond
|
||
0, 240, 32, 256, // crayon 1: couleur (22)
|
||
0, 160, 32, 192, // crayon 1: dessus
|
||
0, 192, 32, 256, // crayon 1: pointe
|
||
32, 240, 64, 256, // crayon 2: couleur
|
||
32, 160, 64, 192, // crayon 2: dessus
|
||
32, 192, 64, 256, // crayon 2: pointe
|
||
64, 240, 96, 256, // crayon 3: couleur
|
||
64, 160, 96, 192, // crayon 3: dessus
|
||
64, 192, 96, 256, // crayon 3: pointe
|
||
96, 240, 128, 256, // crayon 4: couleur
|
||
96, 160, 128, 192, // crayon 4: dessus
|
||
96, 192, 128, 256, // crayon 4: pointe
|
||
128, 240, 160, 256, // crayon 5: couleur
|
||
128, 160, 160, 192, // crayon 5: dessus
|
||
128, 192, 160, 256, // crayon 5: pointe
|
||
160, 240, 192, 256, // crayon 6: couleur
|
||
160, 160, 192, 192, // crayon 6: dessus
|
||
160, 192, 192, 256, // crayon 6: pointe
|
||
192, 240, 224, 256, // crayon 7: couleur
|
||
192, 160, 224, 192, // crayon 7: dessus
|
||
192, 192, 224, 256, // crayon 7: pointe
|
||
224, 240, 256, 256, // crayon 8: couleur
|
||
224, 160, 256, 192, // crayon 8: dessus
|
||
224, 192, 256, 256, // crayon 8: pointe
|
||
-1
|
||
};
|
||
|
||
static int tablePartKi[] = // kid.tga
|
||
{
|
||
0, 0, 128, 53, // ciseaux
|
||
128, 0, 256, 128, // CD
|
||
0, 0, 8, 8, // livre 1: fond
|
||
8, 0, 16, 8, // livre 2: fond
|
||
16, 0, 24, 8, // livre: fond
|
||
24, 0, 32, 8, // livre: fond
|
||
32, 0, 40, 8, // livre: fond
|
||
40, 0, 48, 8, // livre: fond
|
||
0, 53, 22, 138, // livre 1: tranche
|
||
22, 53, 86, 138, // livre 1: face
|
||
0, 138, 22, 224, // livre 2: tranche
|
||
22, 138, 86, 224, // livre 2: face
|
||
86, 53, 94, 85, // livre: pages
|
||
94, 53, 110, 139, // livre: tranche
|
||
110, 53, 126, 139, // livre: tranche
|
||
86, 139, 102, 225, // livre: tranche
|
||
102, 139, 118, 225, // livre: tranche
|
||
118, 139, 134, 225, // livre: tranche
|
||
64, 0, 72, 8, // fauille: fond
|
||
155, 155, 256, 256, // feuille: carreaux
|
||
72, 0, 80, 8, // lampe
|
||
80, 0, 88, 8, // lampe
|
||
80, 8, 88, 16, // ampoule
|
||
72, 8, 80, 16, // rayons (23)
|
||
86, 85, 94, 139, // lampe
|
||
0, 224, 32, 256, // lampe rotule
|
||
64, 8, 72, 16, // arrosoir: fond
|
||
134, 128, 142, 256, // arrosoir: corps
|
||
142, 128, 150, 256, // arrosoir: tuyau
|
||
128, 225, 134, 256, // arrosoir: int<6E>rieur
|
||
32, 224, 64, 256, // arrosoir: ponneau
|
||
56, 8, 64, 16, // skate: roues (31)
|
||
48, 8, 56, 16, // skate: axes
|
||
40, 8, 48, 16, // skate: grip
|
||
32, 8, 40, 16, // skate: tranche
|
||
24, 8, 32, 16, // skate: dessous
|
||
150, 128, 200, 256, // skate: motif 1
|
||
200, 128, 250, 256, // skate: motif 2
|
||
64, 224, 96, 256, // skate: roue (38)
|
||
96, 225, 104, 256, // skate: amortisseur
|
||
-1
|
||
};
|
||
|
||
static int tablePartKi2[] = // kid2.tga
|
||
{
|
||
2, 2, 62, 62, // coca: dessus
|
||
0, 64, 8, 192, // coca: flan
|
||
8, 64, 96, 192, // coca: logo
|
||
128, 0, 256, 85, // carton
|
||
128, 85, 256, 91, // carton tranche
|
||
128, 128, 256, 256, // roue
|
||
192, 96, 256, 128, // pneu
|
||
184, 96, 192, 128, // jante
|
||
128, 96, 160, 128, // int<6E>rieur
|
||
160, 96, 168, 104, // porte bois
|
||
160, 104, 168, 112, // porte m<>tal
|
||
160, 112, 184, 128, // vitre
|
||
96, 0, 128, 256, // bouteille: corps (12)
|
||
64, 0, 96, 32, // bouteille: bouchon
|
||
168, 96, 176, 104, // bouteille: vert
|
||
0, 192, 96, 224, // bois clair
|
||
0, 224, 96, 256, // bois fonc<6E>
|
||
64, 32, 96, 64, // bateau
|
||
168, 104, 176, 112, // ballon (18)
|
||
176, 104, 184, 112, // ballon
|
||
176, 96, 184, 104, // int<6E>rieur caisse
|
||
-1
|
||
};
|
||
|
||
static int tablePartKi3[] = // kid3.tga
|
||
{
|
||
0, 0, 32, 28, // <20>crou: flan
|
||
0, 28, 32, 44, // <20>crou: profil
|
||
0, 44, 32, 60, // <20>crou: pas de vis
|
||
0, 60, 32, 64, // tuyau
|
||
0, 64, 32, 68, // tuyau
|
||
0, 68, 8, 76, // tuyau
|
||
0, 76, 32, 108, // plastic
|
||
8, 68, 16, 76, // saut: gris clair (7)
|
||
16, 68, 24, 76, // saut: gris fonc<6E>
|
||
24, 68, 32, 76, // saut: gris bois
|
||
0, 108, 32, 140, // saut: rotule
|
||
0, 140, 32, 144, // saut: axe
|
||
128, 0, 256, 128, // saut: flan
|
||
0, 144, 8, 152, // basket: gris fonc<6E> (13)
|
||
8, 144, 16, 152, // basket: gris clair
|
||
16, 144, 24, 152, // basket: gris lacets
|
||
24, 144, 32, 152, // basket: gris semelle
|
||
0, 152, 8, 181, // basket: int<6E>rieur
|
||
0, 181, 192, 256, // basket: c<>t<EFBFBD>
|
||
192, 181, 226, 256, // basket: arri<72>re
|
||
32, 135, 96, 181, // basket: dessus (20)
|
||
96, 168, 128, 181, // basket: avant
|
||
8, 152, 16, 160, // chaise: plastique
|
||
16, 152, 24, 160, // chaise: m<>tal
|
||
32, 0, 64, 32, // chaise: roue
|
||
8, 177, 24, 181, // chaise: roue
|
||
226, 181, 234, 256, // chaise: piston (26)
|
||
64, 96, 128, 128, // chaise: relief
|
||
96, 135, 128, 167, // chaise: dessous
|
||
32, 128, 250, 135, // paille 1
|
||
38, 128, 256, 135, // paille 2
|
||
234, 181, 242, 256, // allumette
|
||
8, 160, 16, 168, // allumette (dessus)
|
||
128, 135, 224, 181, // panneau
|
||
242, 135, 256, 256, // poteau (34)
|
||
24, 152, 32, 160, // clou
|
||
16, 160, 24, 168, // tuyau m<>talique
|
||
112, 181, 192, 185, // tuyau int<6E>rieur
|
||
32, 32, 48, 80, // pas de vis
|
||
24, 160, 32, 168, // ventillateur: plastique (39)
|
||
40, 80, 56, 96, // ventillateur: plastique d<>grad<61>
|
||
8, 168, 16, 176, // ventillateur: m<>tal
|
||
32, 80, 40, 112, // ventillateur: socle 1
|
||
64, 0, 96, 16, // ventillateur: socle 2
|
||
48, 32, 56, 80, // ventillateur: socle 3
|
||
64, 16, 96, 32, // ventillateur: moteur flan
|
||
96, 0, 128, 32, // ventillateur: moteur face
|
||
102, 6, 122, 26, // ventillateur: socle dessus
|
||
16, 168, 24, 176, // pot: uni (48)
|
||
56, 32, 64, 64, // pot: haut
|
||
56, 64, 64, 96, // pot: bas
|
||
64, 32, 128, 96, // pot: terre
|
||
-1
|
||
};
|
||
|
||
static int tablePartF[] = // factory.tga
|
||
{
|
||
0, 0, 152, 152, // plancher octogonal fabrique
|
||
50, 50, 102, 102, // dessus pile
|
||
0, 152, 128, 252, // avant
|
||
128, 152, 256, 252, // arri<72>re
|
||
152, 28, 225, 128, // c<>t<EFBFBD>
|
||
152, 28, 176, 128, // c<>t<EFBFBD> partiel
|
||
152, 0, 216, 16, // hachures
|
||
236, 0, 256, 40, // axe
|
||
152, 128, 224, 152, // support cible
|
||
-1
|
||
};
|
||
|
||
static int tablePartD[] = // derrick.tga
|
||
{
|
||
0, 0, 64, 32, // grand c<>t<EFBFBD>
|
||
64, 0, 96, 24, // petit c<>t<EFBFBD>
|
||
96, 0, 136, 24, // attention
|
||
0, 32, 8, 160, // tube 1
|
||
8, 32, 16, 96, // tube 2
|
||
16, 32, 24, 160, // pilier
|
||
24, 32, 32, 160, // tige foret
|
||
32, 32, 40, 160, // tige destructeur
|
||
8, 96, 16, 128, // foret
|
||
136, 0, 256, 120, // plancher octogonal station de recharge
|
||
40, 32, 64, 56, // cube m<>tal
|
||
64, 24, 128, 48, // c<>t<EFBFBD> tour haut
|
||
64, 48, 128, 229, // c<>t<EFBFBD> tour bas
|
||
136, 120, 256, 240, // int<6E>rieur usine
|
||
0, 160, 64, 224, // to<74>t usine
|
||
-1
|
||
};
|
||
|
||
static int tablePartC[] = // convert.tga
|
||
{
|
||
0, 0, 120, 120, // plancher octogonal convertisseur
|
||
0, 120, 128, 176, // grand c<>t<EFBFBD>
|
||
128, 120, 192, 176, // petit c<>t<EFBFBD>
|
||
192, 120, 256, 184, // couvercle convertisseur
|
||
120, 0, 216, 64, // face trianble
|
||
216, 0, 248, 64, // c<>t<EFBFBD> triangle
|
||
120, 64, 160, 84, // axe
|
||
0, 141, 128, 176, // recherche: base
|
||
0, 176, 128, 214, // recherche: haut
|
||
0, 214, 128, 252, // recherche: haut (!)
|
||
174, 64, 190, 120, // recherche: montant
|
||
190, 64, 206, 120, // recherche: montant
|
||
206, 64, 254, 85, // radar
|
||
192, 168, 256, 232, // hachures carr<72>es
|
||
248, 0, 256, 64, // c<>ne fabrique de piles
|
||
128, 176, 192, 240, // dessus centrale nucl<63>aire
|
||
120, 85, 174, 120, // technicien, visage
|
||
206, 106, 256, 120, // technicien, casquette
|
||
160, 64, 174, 78, // technicien, visi<73>re
|
||
-1
|
||
};
|
||
|
||
static int tablePartS[] = // search.tga
|
||
{
|
||
0, 0, 128, 128, // usine 1
|
||
128, 0, 256, 128, // usine 2
|
||
0, 128, 128, 256, // pile
|
||
128, 128, 228, 240, // support pile
|
||
228, 128, 256, 184, // antenne
|
||
128, 128, 192, 160, // contr<74>le 1
|
||
128, 160, 192, 192, // contr<74>le 2
|
||
128, 192, 192, 224, // contr<74>le 3
|
||
128, 224, 192, 256, // contr<74>le 4
|
||
-1
|
||
};
|
||
|
||
static int tablePartP[] = // plant.tga
|
||
{
|
||
0, 160, 48, 256, // feuille 1
|
||
0, 0, 94, 100, // feuille 2
|
||
48, 156, 108, 256, // feuille 3
|
||
94, 0, 104, 100, // tige 1
|
||
185, 0, 195, 100, // tige 2
|
||
108, 100, 182, 256, // foug<75>re
|
||
104, 0, 144, 100, // courge
|
||
203, 0, 256, 83, // armature derrick r<>solution C
|
||
-1
|
||
};
|
||
|
||
static int tablePartV[] = // vegetal.tga
|
||
{
|
||
0, 0, 94, 100, // racine
|
||
186, 0, 256, 256, // tronc
|
||
162, 0, 168, 128, // mat drapeau bleu
|
||
168, 0, 174, 128, // mat drapeau rouge
|
||
174, 0, 180, 128, // mat drapeau vert
|
||
180, 0, 186, 128, // mat drapeau jaune
|
||
180, 128, 186, 256, // mat drapeau violet
|
||
94, 0, 107, 32, // drapeau bleu
|
||
107, 0, 120, 32, // drapeau rouge
|
||
120, 0, 133, 32, // drapeau vert
|
||
133, 0, 146, 32, // drapeau jaune
|
||
146, 0, 159, 32, // drapeau violet
|
||
94, 64, 126, 96, // verre 1
|
||
126, 64, 158, 86, // verre 2
|
||
128, 128, 180, 144, // verre 3a
|
||
128, 144, 180, 160, // verre 3b
|
||
128, 94, 162, 128, // verre 4
|
||
0, 100, 32, 228, // champignon 1
|
||
32, 100, 48, 228, // champignon 1
|
||
48, 100, 112, 228, // champignon 2
|
||
112, 100, 128, 228, // champignon 2
|
||
128, 160, 180, 212, // tronc (21)
|
||
-1
|
||
};
|
||
|
||
static int tablePartM[] = // mother.tga
|
||
{
|
||
0, 0, 128, 128, // corps arri<72>re
|
||
128, 0, 192, 128, // corps avant
|
||
0, 128, 64, 192, // t<>te
|
||
64, 128, 192, 160, // pince ext.
|
||
64, 160, 192, 192, // pince int.
|
||
0, 192, 64, 256, // mire
|
||
-1
|
||
};
|
||
|
||
static int tablePartA[] = // ant.tga
|
||
{
|
||
0, 0, 64, 64, // queue
|
||
0, 96, 128, 160, // queue abeille
|
||
64, 0, 128, 64, // corps
|
||
128, 0, 192, 64, // t<>te
|
||
0, 64, 64, 72, // patte
|
||
0, 72, 64, 80, // antenne
|
||
64, 64, 150, 96, // queue ver
|
||
150, 64, 182, 96, // corps ver
|
||
182, 64, 256, 96, // t<>te ver
|
||
224, 32, 256, 64, // articulation ver
|
||
128, 96, 220, 160, // aile
|
||
0, 80, 16, 96, // oeil
|
||
200, 0, 208, 8, // vert clair
|
||
200, 8, 208, 16, // vert fonc<6E>
|
||
0, 160, 64, 224, // corps araign<67>e
|
||
64, 160, 128, 192, // t<>te araign<67>e
|
||
208, 0, 216, 64, // patte araign<67>e
|
||
216, 0, 224, 32, // patte araign<67>e
|
||
224, 0, 256, 8, // antenne araign<67>e
|
||
192, 0, 200, 8, // brun clair
|
||
192, 8, 200, 16, // brun fonc<6E>
|
||
128, 160, 256, 256, // SatCom
|
||
-1
|
||
};
|
||
|
||
static int tablePartH[] = // human.tga
|
||
{
|
||
0, 0, 64, 64, // vissi<73>re
|
||
64, 0, 96, 64, // cuisse
|
||
96, 0, 128, 64, // jambe
|
||
128, 0, 192, 32, // bras
|
||
128, 32, 192, 64, // avant-bras
|
||
0, 64, 128, 224, // ventre
|
||
128, 64, 256, 224, // dos
|
||
64, 224, 112, 256, // dessus pied
|
||
144, 224, 168, 240, // dessous pied
|
||
112, 224, 144, 240, // c<>t<EFBFBD> pied
|
||
112, 224, 128, 240, // c<>t<EFBFBD> pied
|
||
0, 224, 64, 256, // gant
|
||
168, 224, 200, 256, // oreille
|
||
112, 240, 144, 256, // ligne casque
|
||
200, 224, 208, 256, // int<6E>rieur coup
|
||
240, 0, 244, 64, // bombone orange
|
||
244, 0, 248, 64, // bombone orange (reflet)
|
||
248, 0, 252, 64, // bombone bleu
|
||
252, 0, 256, 64, // bombone bleu (reflet)
|
||
144, 240, 156, 256, // gris habit
|
||
156, 240, 168, 256, // gris articulation
|
||
//? 208, 224, 256, 256, // SatCom
|
||
192, 0, 240, 64, // quartz
|
||
-1
|
||
};
|
||
|
||
static int tablePartG[] = // apollo.tga
|
||
{
|
||
0, 0, 64, 64, // rev<65>tement LEM
|
||
64, 0, 128, 64, // rev<65>tement LEM
|
||
128, 8, 136, 128, // pied
|
||
0, 64, 64, 128, // roue
|
||
136, 24, 152, 44, // profil pneu
|
||
136, 8, 160, 24, // garde boue
|
||
64, 64, 128, 128, // si<73>ge
|
||
64, 128, 128, 192, // si<73>ge
|
||
64, 192, 128, 212, // si<73>ge
|
||
128, 128, 240, 192, // moteur
|
||
0, 192, 28, 256, // moteur
|
||
32, 128, 60, 256, // moteur
|
||
224, 0, 256, 128, // avant
|
||
206, 0, 224, 128, // avant
|
||
136, 44, 168, 62, // avant
|
||
64, 212, 108, 256, // panneau de commande
|
||
198, 0, 206, 128, // mat
|
||
190, 64, 198, 128, // mat
|
||
160, 8, 176, 24, // cam<61>ra
|
||
176, 8, 192, 24, // moyeu
|
||
136, 64, 168, 96, // module
|
||
168, 64, 190, 96, // module
|
||
136, 96, 168, 128, // module
|
||
128, 192, 230, 252, // drapeau
|
||
0, 128, 32, 192, // antenne
|
||
128, 0, 136, 8, // jaune
|
||
136, 0, 144, 8, // beige
|
||
144, 0, 152, 8, // brun
|
||
168, 0, 176, 8, // gris tr<74>s clair
|
||
152, 0, 160, 8, // gris clair
|
||
160, 0, 168, 8, // gris fonc<6E>
|
||
-1
|
||
};
|
||
|
||
static int tablePartB[] = // base1.tga
|
||
{
|
||
0, 0, 80, 256, // int<6E>rieur porte
|
||
80, 0, 88, 256, // tranche porte
|
||
116, 0, 180, 64, // coiffe 1
|
||
116, 64, 180, 102, // coiffe 2
|
||
180, 0, 244, 37, // base
|
||
180, 37, 196, 101, // support
|
||
88, 0, 116, 256, // colonne
|
||
212, 37, 256, 128, // suppl<70>ment
|
||
128, 128, 256, 256, // 1/4 du sol
|
||
196, 37, 212, 53, // gris fonc<6E>
|
||
196, 53, 212, 69, // gris clair
|
||
-1
|
||
};
|
||
|
||
static int tablePartCe[] = // cellar01.tga
|
||
{
|
||
0, 128, 64, 192, // briques
|
||
64, 128, 128, 192, // briques
|
||
128, 128, 192, 192, // briques
|
||
192, 128, 256, 192, // briques
|
||
-1
|
||
};
|
||
|
||
static int tablePartFa[] = // face01.tga
|
||
{
|
||
0, 0, 256, 256, // visage
|
||
-1
|
||
};
|
||
|
||
// Retourne le pointeur la table.
|
||
|
||
int* CModel::RetTextureTable()
|
||
{
|
||
if ( m_textureRank == 0 ) return tablePartT;
|
||
if ( m_textureRank == 1 ) return tablePartR;
|
||
if ( m_textureRank == 2 ) return tablePartW;
|
||
if ( m_textureRank == 3 ) return tablePartDr;
|
||
if ( m_textureRank == 4 ) return tablePartKi;
|
||
if ( m_textureRank == 5 ) return tablePartKi2;
|
||
if ( m_textureRank == 6 ) return tablePartKi3;
|
||
if ( m_textureRank == 7 ) return tablePartF;
|
||
if ( m_textureRank == 8 ) return tablePartD;
|
||
if ( m_textureRank == 9 ) return tablePartC;
|
||
if ( m_textureRank == 10 ) return tablePartS;
|
||
if ( m_textureRank == 11 ) return tablePartP;
|
||
if ( m_textureRank == 12 ) return tablePartV;
|
||
if ( m_textureRank == 13 ) return tablePartM;
|
||
if ( m_textureRank == 14 ) return tablePartA;
|
||
if ( m_textureRank == 15 ) return tablePartH;
|
||
if ( m_textureRank == 16 ) return tablePartG;
|
||
if ( m_textureRank == 17 ) return tablePartB;
|
||
if ( m_textureRank == 18 ) return tablePartCe;
|
||
if ( m_textureRank == 19 ) return tablePartFa;
|
||
if ( m_textureRank == 20 ) return tablePartFa;
|
||
if ( m_textureRank == 21 ) return tablePartFa;
|
||
if ( m_textureRank == 22 ) return tablePartFa;
|
||
return 0;
|
||
}
|
||
|
||
// Updates the part of texture.
|
||
|
||
void CModel::TexturePartUpdate()
|
||
{
|
||
int *table;
|
||
|
||
table = RetTextureTable();
|
||
if ( table == 0 ) return;
|
||
|
||
m_textureInf.x = (table[m_texturePart*4+0]+0.5f)/256.0f;
|
||
m_textureInf.y = (table[m_texturePart*4+1]+0.5f)/256.0f;
|
||
m_textureSup.x = (table[m_texturePart*4+2]-0.5f)/256.0f;
|
||
m_textureSup.y = (table[m_texturePart*4+3]-0.5f)/256.0f;
|
||
|
||
PutTextureValues();
|
||
}
|
||
|
||
// Changes the texture.
|
||
|
||
void CModel::TextureRankChange(int step)
|
||
{
|
||
m_textureRank += step;
|
||
|
||
if ( m_textureRank >= MAX_NAMES ) m_textureRank = 0;
|
||
if ( m_textureRank < 0 ) m_textureRank = MAX_NAMES-1;
|
||
|
||
if ( m_textureRank == 0 ) strcpy(m_textureName, "lemt.tga");
|
||
if ( m_textureRank == 1 ) strcpy(m_textureName, "roller.tga");
|
||
if ( m_textureRank == 2 ) strcpy(m_textureName, "subm.tga");
|
||
if ( m_textureRank == 3 ) strcpy(m_textureName, "drawer.tga");
|
||
if ( m_textureRank == 4 ) strcpy(m_textureName, "kid.tga");
|
||
if ( m_textureRank == 5 ) strcpy(m_textureName, "kid2.tga");
|
||
if ( m_textureRank == 6 ) strcpy(m_textureName, "kid3.tga");
|
||
if ( m_textureRank == 7 ) strcpy(m_textureName, "factory.tga");
|
||
if ( m_textureRank == 8 ) strcpy(m_textureName, "derrick.tga");
|
||
if ( m_textureRank == 9 ) strcpy(m_textureName, "convert.tga");
|
||
if ( m_textureRank == 10 ) strcpy(m_textureName, "search.tga");
|
||
if ( m_textureRank == 11 ) strcpy(m_textureName, "plant.tga");
|
||
if ( m_textureRank == 12 ) strcpy(m_textureName, "vegetal.tga");
|
||
if ( m_textureRank == 13 ) strcpy(m_textureName, "mother.tga");
|
||
if ( m_textureRank == 14 ) strcpy(m_textureName, "ant.tga");
|
||
if ( m_textureRank == 15 ) strcpy(m_textureName, "human.tga");
|
||
if ( m_textureRank == 16 ) strcpy(m_textureName, "apollo.tga");
|
||
if ( m_textureRank == 17 ) strcpy(m_textureName, "base1.tga");
|
||
if ( m_textureRank == 18 ) strcpy(m_textureName, "cellar01.tga");
|
||
if ( m_textureRank == 19 ) strcpy(m_textureName, "face01.tga");
|
||
if ( m_textureRank == 20 ) strcpy(m_textureName, "face02.tga");
|
||
if ( m_textureRank == 21 ) strcpy(m_textureName, "face03.tga");
|
||
if ( m_textureRank == 22 ) strcpy(m_textureName, "face04.tga");
|
||
|
||
m_texturePart = 0;
|
||
}
|
||
|
||
// Changes the part of texture.
|
||
|
||
void CModel::TexturePartChange(int step)
|
||
{
|
||
int *table;
|
||
|
||
table = RetTextureTable();
|
||
if ( table == 0 ) return;
|
||
|
||
m_texturePart ++;
|
||
|
||
if ( table[m_texturePart*4] == -1 )
|
||
{
|
||
m_texturePart = 0;
|
||
}
|
||
|
||
TexturePartUpdate();
|
||
}
|
||
|
||
|