16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 06:39:18 +02:00
This commit is contained in:
VB
2017-02-20 19:03:27 +01:00
parent e24ad4449e
commit b73fec0c5a
16 changed files with 479 additions and 293 deletions

View File

@@ -22,12 +22,13 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
#include "Texture.h"
#include "Timer.h"
#include "mtable.h"
#include "sn_utils.h"
//---------------------------------------------------------------------------
using namespace Mtable;
double TSubModel::fSquareDist = 0;
int TSubModel::iInstance; // numer renderowanego egzemplarza obiektu
size_t TSubModel::iInstance; // numer renderowanego egzemplarza obiektu
texture_manager::size_type *TSubModel::ReplacableSkinId = NULL;
int TSubModel::iAlpha = 0x30300030; // maska do testowania flag tekstur wymiennych
TModel3d *TSubModel::pRoot; // Ra: tymczasowo wskaźnik na model widoczny z submodelu
@@ -47,24 +48,6 @@ int TSubModelInfo::iTotalTextures = 0; // długość obszaru tekstur
int TSubModelInfo::iCurrent = 0; // aktualny obiekt
TSubModelInfo *TSubModelInfo::pTable = NULL; // tabele obiektów pomocniczych
char *TStringPack::String(int n)
{ // zwraca wskaźnik do łańcucha o podanym numerze
if (index ? n < (index[1] >> 2) - 2 : false)
return data + 8 + index[n + 2]; // indeks upraszcza kwestię wyszukiwania
// jak nie ma indeksu, to trzeba szukać
int max = *((int *)(data + 4)); // długość obszaru łańcuchów
char *ptr = data + 8; // począek obszaru łańcuchów
for (int i = 0; i < n; ++i)
{ // wyszukiwanie łańcuchów nie jest zbyt optymalne, ale nie musi być
while (*ptr)
++ptr; // wyszukiwanie zera
++ptr; // pominięcie zera
if (ptr > data + max)
return NULL; // zbyt wysoki numer
}
return ptr;
};
TSubModel::TSubModel()
{
ZeroMemory(this, sizeof(TSubModel)); // istotne przy zapisywaniu wersji binarnej
@@ -114,7 +97,8 @@ void TSubModel::FirstInit()
iTexture = 0; // brak tekstury
// asName="";
// asTexture="";
pName = pTexture = NULL;
pName = "";
pTexture = "";
f4Ambient[0] = f4Ambient[1] = f4Ambient[2] = f4Ambient[3] = 1.0; //{1,1,1,1};
f4Diffuse[0] = f4Diffuse[1] = f4Diffuse[2] = f4Diffuse[3] = 1.0; //{1,1,1,1};
f4Specular[0] = f4Specular[1] = f4Specular[2] = 0.0;
@@ -134,8 +118,6 @@ TSubModel::~TSubModel()
SafeDelete(Child);
delete fMatrix; // własny transform trzeba usunąć (zawsze jeden)
delete[] Vertices;
delete[] pTexture;
delete[] pName;
}
/*
else
@@ -151,15 +133,7 @@ void TSubModel::TextureNameSet(const char *n)
// ile nie jest wczytany z E3D
if (iFlags & 0x0200)
{ // tylko jeżeli submodel zosta utworzony przez new
delete[] pTexture; // usunięcie poprzedniej
int i = strlen(n);
if (i)
{ // utworzenie nowej
pTexture = new char[i + 1];
strcpy(pTexture, n);
}
else
pTexture = NULL;
pTexture = std::string(n);
}
};
@@ -167,17 +141,7 @@ void TSubModel::NameSet(const char *n)
{ // ustawienie nazwy submodelu, o ile
// nie jest wczytany z E3D
if (iFlags & 0x0200)
{ // tylko jeżeli submodel zosta utworzony przez new
delete[] pName; // usunięcie poprzedniej
int i = strlen(n);
if (i)
{ // utworzenie nowej
pName = new char[i + 1];
strcpy(pName, n);
}
else
pName = NULL;
}
pName = std::string(n);
};
// int TSubModel::SeekFaceNormal(DWORD *Masks, int f,DWORD dwMask,vector3
@@ -368,8 +332,8 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
parser >> discard >> bWire >> discard >> fWireSize >> discard;
Opacity = readIntAsDouble(parser,
100.0f); // wymagane jest 0 dla szyb, 100 idzie w nieprzezroczyste
if (Opacity > 1.0)
Opacity *= 0.01; // w 2013 był błąd i aby go obejść, trzeba było wpisać 10000.0
if (Opacity > 1.0f)
Opacity *= 0.01f; // w 2013 był błąd i aby go obejść, trzeba było wpisać 10000.0
if ((Global::iConvertModels & 1) == 0) // dla zgodności wstecz
Opacity = 0.0; // wszystko idzie w przezroczyste albo zależnie od tekstury
if (!parser.expectToken("map:"))
@@ -961,11 +925,15 @@ TSubModel *TSubModel::GetFromName(char const *search, bool i)
// std::transform(search.begin(),search.end(),search.begin(),ToLower());
// search=search.LowerCase();
// AnsiString name=AnsiString();
if (pName && search)
if ((i ? stricmp(pName, search) : strcmp(pName, search)) == 0)
std::string search_lc = std::string(search);
if (i)
std::transform(search_lc.begin(), search_lc.end(), search_lc.begin(), ::tolower);
std::string pName_lc = pName;
if (i)
std::transform(pName_lc.begin(), pName_lc.end(), pName_lc.begin(), ::tolower);
if (pName.size() && search)
if (pName_lc == search_lc)
return this;
else if (pName == search)
return this; // oba NULL
if (Next)
{
result = Next->GetFromName(search);
@@ -1063,7 +1031,7 @@ void TSubModel::RaAnimation(TAnimType a)
TSubModel *sm = ChildGet();
do
{ // pętla po submodelach potomnych i obracanie ich o kąt zależy od czasu
if (sm->pName)
if (sm->pName.size())
{ // musi mieć niepustą nazwę
if ((sm->pName[0]) >= '0')
if ((sm->pName[0]) <= '5') // zegarek ma 6 cyfr maksymalnie
@@ -1220,7 +1188,7 @@ void TSubModel::RenderAlphaDL()
if (eType == TP_TEXT)
{ // tekst renderujemy w specjalny sposób, zamiast
// submodeli z łańcucha Child
int i, j = pasText->size();
size_t i, j = pasText->size();
TSubModel *p;
if (!smLetter)
{ // jeśli nie ma tablicy, to ją stworzyć; miejsce
@@ -1232,7 +1200,7 @@ void TSubModel::RenderAlphaDL()
p = Child;
while (p)
{
smLetter[*p->pName] = p;
smLetter[p->pName[0]] = p;
p = p->Next; // kolejny znak
}
}
@@ -1288,12 +1256,12 @@ void TSubModel::RenderVBO()
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glDrawArrays(eType, iVboPtr,
glDrawArrays(eType, (GLint)iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glDrawArrays(eType, iVboPtr,
glDrawArrays(eType, (GLint)iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
}
}
@@ -1359,7 +1327,7 @@ void TSubModel::RenderVBO()
// blendowaly
glColor3fv(color); // inaczej są białe
glMaterialfv(GL_FRONT, GL_EMISSION, color);
glDrawArrays(GL_POINTS, iVboPtr, iNumVerts); // narysuj wierzchołek z
glDrawArrays(GL_POINTS, (GLint)iVboPtr, iNumVerts); // narysuj wierzchołek z
// VBO
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // co ma ustawiać glColor
@@ -1383,7 +1351,7 @@ void TSubModel::RenderVBO()
// blendowaly
// glMaterialfv(GL_FRONT,GL_EMISSION,f4Diffuse); //zeby swiecilo na
// kolorowo
glDrawArrays(GL_POINTS, iVboPtr,
glDrawArrays(GL_POINTS, (GLint)iVboPtr,
iNumVerts); // narysuj naraz wszystkie punkty z VBO
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
@@ -1459,12 +1427,12 @@ void TSubModel::RenderAlphaVBO()
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glDrawArrays(eType, iVboPtr,
glDrawArrays(eType, (GLint)iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glDrawArrays(eType, iVboPtr,
glDrawArrays(eType, (GLint)iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
}
}
@@ -1539,18 +1507,18 @@ void TSubModel::Info()
if (t != std::string(pTexture))
{ // jeśli się zmieniło
// pName=new char[token.length()+1]; //nie ma sensu skracać tabeli
strcpy(pTexture, t.c_str());
pTexture = t;
}
info->iTextureLen = t.size() + 1; // przygotowanie do zapisania, z zerem na końcu
info->iTextureLen = (int)t.size() + 1; // przygotowanie do zapisania, z zerem na końcu
}
}
else
info->iTexture = TextureID; // nie ma albo wymienna
// if (asName.Length())
if (pName)
if (pName.size())
{
info->iName = info->iTotalNames++; // przydzielenie numeru nazwy w pliku (od 0)
info->iNameLen = strlen(pName) + 1; // z zerem na końcu
info->iNameLen = (int)pName.size() + 1; // z zerem na końcu
}
++info->iCurrent; // przejście do kolejnego obiektu pomocniczego
if (Child)
@@ -1576,73 +1544,14 @@ void TSubModel::InfoSet(TSubModelInfo *info)
TextureID = info->iTexture; // numer tekstury w OpenGL
iName = info->iName; // numer nazwy w obszarze nazw
iMatrix = info->iTransform; // numer macierzy
Next = (TSubModel *)info->iNext; // numer następnego
Child = (TSubModel *)info->iChild; // numer potomnego
iNext = info->iNext; // numer następnego
iChild = info->iChild; // numer potomnego
iFlags &= ~0x200; // nie jest wczytany z tekstowego
// asTexture=asName="";
pTexture = pName = NULL;
pTexture = "";
pName = "";
};
void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v, TStringPack *t, TStringPack *n,
bool dynamic)
{ // ustawienie wskaźników w submodelu
iVisible = 1; // tymczasowo używane
Child = ((int)Child > 0) ? s + (int)Child : NULL; // zerowy nie może być potomnym
Next = ((int)Next > 0) ? s + (int)Next : NULL; // zerowy nie może być następnym
fMatrix = ((iMatrix >= 0) && m) ? m + iMatrix : NULL;
// if (n&&(iName>=0)) asName=AnsiString(n->String(iName)); else asName="";
if (n && (iName >= 0))
{
pName = n->String(iName);
std::string name(pName);
if (false == name.empty())
{ // jeśli dany submodel jest zgaszonym światłem, to
// domyślnie go ukrywamy
if ((name.size() >= 8) && (name.substr(0, 8) == "Light_On"))
{ // jeśli jest światłem numerowanym
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z
}
// obiektem "Light_Off"
else if (dynamic)
{ // inaczej wyłączało smugę w latarniach
if ((name.size() >= 3) && (name.substr(name.size() - 3, 3) == "_on"))
{ // jeśli jest kontrolką w stanie zapalonym
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z
}
}
// obiektem "_off"
}
}
else
pName = NULL;
if (iTexture > 0)
{ // obsługa stałej tekstury
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
// asTexture=AnsiString(t->String(iTexture));
pTexture = t->String(iTexture);
std::string tex = pTexture;
if (tex.find_last_of("/\\") == std::string::npos)
tex.insert(0, Global::asCurrentTexturePath);
TextureID = TextureManager.GetTextureId(tex, szTexturePath);
// TexAlpha=TTexturesManager::GetAlpha(TextureID); //zmienna robocza
// ustawienie cyklu przezroczyste/nieprzezroczyste zależnie od własności
// stałej tekstury
// iFlags=(iFlags&~0x30)|(TTexturesManager::GetAlpha(TextureID)?0x20:0x10);
// //0x10-nieprzezroczysta, 0x20-przezroczysta
if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity 0!
iFlags |= TextureManager.Texture(TextureID).has_alpha ?
0x20 :
0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta
else
iFlags |= 0x10; // normalnie nieprzezroczyste
}
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem
// tablic)
Vertices = v + iVboPtr;
// if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie
// renderowało na siłę
};
void TSubModel::AdjustDist()
{ // aktualizacja odległości faz LoD, zależna od
// rozdzielczości pionowej oraz multisamplingu
@@ -1834,112 +1743,227 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
return result;
};
// E3D deserialization
// http://rainsted.com/pl/Format_binarny_modeli_-_E3D
void TSubModel::deserialize(std::istream &s)
{
iNext = sn_utils::ld_int32(s);
iChild = sn_utils::ld_int32(s);
eType = sn_utils::ld_int32(s);
iName = sn_utils::ld_int32(s);
b_Anim = (TAnimType)sn_utils::ld_int32(s);
iFlags = sn_utils::ld_int32(s);
iMatrix = sn_utils::ld_int32(s);
iNumVerts = sn_utils::ld_int32(s);
tVboPtr = sn_utils::ld_int32(s);
iTexture = sn_utils::ld_int32(s);
fVisible = sn_utils::ld_float32(s);
fLight = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
f4Ambient[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
f4Diffuse[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
f4Specular[i] = sn_utils::ld_float32(s);
for (size_t i = 0; i < 4; i++)
f4Emision[i] = sn_utils::ld_float32(s);
fWireSize = sn_utils::ld_float32(s);
fSquareMaxDist = sn_utils::ld_float32(s);
fSquareMinDist = sn_utils::ld_float32(s);
fNearAttenStart = sn_utils::ld_float32(s);
fNearAttenEnd = sn_utils::ld_float32(s);
bUseNearAtten = sn_utils::ld_uint32(s) != 0;
iFarAttenDecay = sn_utils::ld_int32(s);
fFarDecayRadius = sn_utils::ld_float32(s);
fCosFalloffAngle = sn_utils::ld_float32(s);
fCosHotspotAngle = sn_utils::ld_float32(s);
fCosViewAngle = sn_utils::ld_float32(s);
}
void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
{
m_pVNT = nullptr;
Root = nullptr;
float4x4 *tm = nullptr;
std::streampos end = s.tellg() + (std::streampos)size;
while (s.tellg() < end)
{
uint32_t type = sn_utils::ld_uint32(s);
uint32_t size = sn_utils::ld_uint32(s) - 8;
std::streampos end = s.tellg() + (std::streampos)size;
if (type == MAKE_ID4('V', 'N', 'T', '0'))
{
if (m_pVNT != nullptr)
throw std::runtime_error("e3d: duplicated VNT chunk");
size_t vt_cnt = size / 32;
iNumVerts = (int)vt_cnt;
m_nVertexCount = (int)vt_cnt;
m_pVNT = new CVertNormTex[vt_cnt];
for (size_t i = 0; i < vt_cnt; i++)
m_pVNT[i].deserialize(s);
}
else if ((type & 0x00FFFFFF) == MAKE_ID4('S', 'U', 'B', 0))
{
if (Root != nullptr)
throw std::runtime_error("e3d: duplicated SUB chunk");
size_t sm_size = 256 + 64 * (((type & 0xFF000000) >> 24) - '0');
size_t sm_cnt = size / sm_size;
iSubModelsCount = (int)sm_cnt;
Root = new TSubModel[sm_cnt];
size_t pos = s.tellg();
for (size_t i = 0; i < sm_cnt; i++)
{
s.seekg(pos + sm_size * i);
Root[i].deserialize(s);
}
}
else if (type == MAKE_ID4('T', 'R', 'A', '0'))
{
if (tm != nullptr)
throw std::runtime_error("e3d: duplicated TRA chunk");
size_t t_cnt = size / 64;
tm = new float4x4[t_cnt];
for (size_t i = 0; i < t_cnt; i++)
tm[i].deserialize_float32(s);
}
else if (type == MAKE_ID4('T', 'R', 'A', '1'))
{
if (tm != nullptr)
throw std::runtime_error("e3d: duplicated TRA chunk");
size_t t_cnt = size / 128;
tm = new float4x4[t_cnt];
for (size_t i = 0; i < t_cnt; i++)
tm[i].deserialize_float64(s);
}
else if (type == MAKE_ID4('T', 'E', 'X', '0'))
{
if (Textures.size())
throw std::runtime_error("e3d: duplicated TEX chunk");
while (s.tellg() < end)
Textures.push_back(sn_utils::d_str(s));
}
else if (type == MAKE_ID4('N', 'A', 'M', '0'))
{
if (Names.size())
throw std::runtime_error("e3d: duplicated NAM chunk");
while (s.tellg() < end)
Names.push_back(sn_utils::d_str(s));
}
s.seekg(end);
}
if (!Root)
throw std::runtime_error("e3d: no submodels");
if (!m_pVNT)
throw std::runtime_error("e3d: no vertices");
for (size_t i = 0; (int)i < iSubModelsCount; i++)
{
Root[i].BinInit(Root, tm, (float8*)m_pVNT, &Textures, &Names, dynamic);
if (Root[i].ChildGet())
Root[i].ChildGet()->Parent = &Root[i];
if (Root[i].NextGet())
Root[i].NextGet()->Parent = Root[i].Parent;
}
}
void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic)
{ // ustawienie wskaźników w submodelu
iVisible = 1; // tymczasowo używane
Child = (iChild > 0) ? s + iChild : nullptr; // zerowy nie może być potomnym
Next = (iNext > 0) ? s + iNext : nullptr; // zerowy nie może być następnym
fMatrix = ((iMatrix >= 0) && m) ? m + iMatrix : nullptr;
if (n->size() && (iName >= 0))
{
pName = n->at(iName);
if (!pName.empty())
{ // jeśli dany submodel jest zgaszonym światłem, to
// domyślnie go ukrywamy
if ((pName.size() >= 8) && (pName.substr(0, 8) == "Light_On"))
{ // jeśli jest światłem numerowanym
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z
}
// obiektem "Light_Off"
else if (dynamic)
{ // inaczej wyłączało smugę w latarniach
if ((pName.size() >= 3) && (pName.substr(pName.size() - 3, 3) == "_on"))
{ // jeśli jest kontrolką w stanie zapalonym
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z
}
}
// obiektem "_off"
}
}
else
pName = "";
if (iTexture > 0)
{ // obsługa stałej tekstury
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
// asTexture=AnsiString(t->String(iTexture));
pTexture = t->at(iTexture);
if (pTexture.find_last_of("/\\") == std::string::npos)
pTexture.insert(0, Global::asCurrentTexturePath);
TextureID = TextureManager.GetTextureId(pTexture, szTexturePath);
// TexAlpha=TTexturesManager::GetAlpha(TextureID); //zmienna robocza
// ustawienie cyklu przezroczyste/nieprzezroczyste zależnie od własności
// stałej tekstury
// iFlags=(iFlags&~0x30)|(TTexturesManager::GetAlpha(TextureID)?0x20:0x10);
// //0x10-nieprzezroczysta, 0x20-przezroczysta
if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity 0!
iFlags |= TextureManager.Texture(TextureID).has_alpha ?
0x20 :
0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta
else
iFlags |= 0x10; // normalnie nieprzezroczyste
}
else
TextureID = iTexture;
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem
// tablic)
iVboPtr = tVboPtr;
Vertices = v + iVboPtr;
// if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie
// renderowało na siłę
};
void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
{ // wczytanie modelu z pliku binarnego
WriteLog("Loading - binary model: " + FileName);
int i = 0, j, k, ch, size;
std::ifstream file(FileName, std::ios::binary);
/* TFileStream *fs = new TFileStream(AnsiString(FileName), fmOpenRead);
size = fs->Size >> 2;
iModel = new int[size]; // ten wskaźnik musi być w modelu, aby zwolnić pamięć
fs->Read(iModel, fs->Size); // wczytanie pliku
delete fs;
*/ {
std::ifstream file(FileName, std::ios::binary | std::ios::ate);
file.unsetf(std::ios::skipws);
size = file.tellg(); // ios::ate already positioned us at the end of the file
iModel = new int[size >> 2]; // ten wskaźnik musi być w modelu, aby zwolnić pamięć
file.seekg(0, std::ios::beg); // rewind the caret afterwards
file.read(reinterpret_cast<char *>(iModel), size);
}
float4x4 *m = NULL; // transformy
// zestaw kromek:
while ((i << 2) < size) // w pliku może być kilka modeli
{
ch = iModel[i]; // nazwa kromki
j = i + (iModel[i + 1] >> 2); // początek następnej kromki
if (ch == MAKE_ID4('E', '3', 'D', '0')) // główna: 'E3D0',len,pod-kromki
{ // tylko tę kromkę znamy, może kiedyś jeszcze DOF się zrobi
i += 2;
while (i < j)
{ // przetwarzanie kromek wewnętrznych
ch = iModel[i]; // nazwa kromki
k = (iModel[i + 1] >> 2); // długość aktualnej kromki
switch (ch)
{
case MAKE_ID4('M', 'D', 'L',
'0'): // zmienne modelu: 'E3D0',len,(informacje o modelu)
break;
case MAKE_ID4('V', 'N', 'T',
'0'): // wierzchołki: 'VNT0',len,(32 bajty na wierzchołek)
iNumVerts = (k - 2) >> 3;
m_nVertexCount = iNumVerts;
m_pVNT = (CVertNormTex *)(iModel + i + 2);
break;
case MAKE_ID4('S', 'U', 'B', '0'): // submodele: 'SUB0',len,(256 bajtów na submodel)
iSubModelsCount = (k - 2) / 64;
Root =
(TSubModel *)(iModel + i + 2); // numery na wskaźniki przetworzymy później
break;
case MAKE_ID4('S', 'U', 'B', '1'): // submodele: 'SUB1',len,(320 bajtów na submodel)
iSubModelsCount = (k - 2) / 80;
Root =
(TSubModel *)(iModel + i + 2); // numery na wskaźniki przetworzymy później
for (ch = 1; ch < iSubModelsCount;
++ch) // trzeba przesunąć bliżej, bo 256 wystarczy
MoveMemory(((char *)Root) + 256 * ch, ((char *)Root) + 320 * ch, 256);
break;
case MAKE_ID4('T', 'R', 'A', '0'): // transformy: 'TRA0',len,(64 bajty na transform)
m = (float4x4 *)(iModel + i + 2); // tabela transformów
break;
case MAKE_ID4('T', 'R', 'A',
'1'): // transformy: 'TRA1',len,(128 bajtów na transform)
m = (float4x4 *)(iModel + i + 2); // tabela transformów
for (ch = 0; ch < ((k - 2) >> 1); ++ch)
*(((float *)m) + ch) = *(((double *)m) + ch); // przepisanie double do float
break;
case MAKE_ID4('I', 'D', 'X',
'1'): // indeksy 1B: 'IDX2',len,(po bajcie na numer wierzchołka)
break;
case MAKE_ID4('I', 'D', 'X',
'2'): // indeksy 2B: 'IDX2',len,(po 2 bajty na numer wierzchołka)
break;
case MAKE_ID4('I', 'D', 'X',
'4'): // indeksy 4B: 'IDX4',len,(po 4 bajty na numer wierzchołka)
break;
case MAKE_ID4('T', 'E', 'X',
'0'): // tekstury: 'TEX0',len,(łańcuchy zakończone zerem - pliki
// tekstur)
Textures.Init((char *)(iModel + i)); //łącznie z nagłówkiem
break;
case MAKE_ID4('T', 'I', 'X', '0'): // indeks nazw tekstur
Textures.InitIndex((int *)(iModel + i)); //łącznie z nagłówkiem
break;
case MAKE_ID4('N', 'A', 'M',
'0'): // nazwy: 'NAM0',len,(łańcuchy zakończone zerem - nazwy
// submodeli)
Names.Init((char *)(iModel + i)); //łącznie z nagłówkiem
break;
case MAKE_ID4('N', 'I', 'X', '0'): // indeks nazw submodeli
Names.InitIndex((int *)(iModel + i)); //łącznie z nagłówkiem
break;
}
i += k; // przejście do kolejnej kromki
}
}
i = j;
}
for (i = 0; i < iSubModelsCount; ++i)
{ // aktualizacja wskaźników w submodelach
Root[i].BinInit(Root, m, (float8 *)m_pVNT, &Textures, &Names, dynamic);
if (Root[i].ChildGet())
Root[i].ChildGet()->Parent = Root + i; // wpisanie wskaźnika nadrzędnego do potmnego
if (Root[i].NextGet())
Root[i].NextGet()->Parent =
Root[i].Parent; // skopiowanie wskaźnika nadrzędnego do kolejnego
}
iFlags &= ~0x0200;
return;
uint32_t type = sn_utils::ld_uint32(file);
uint32_t size = sn_utils::ld_uint32(file) - 8;
if (type != MAKE_ID4('E', '3', 'D', '0'))
throw std::runtime_error("e3d: unknown main chunk");
deserialize(file, size, dynamic);
file.close();
};
void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
@@ -2084,7 +2108,7 @@ void TModel3d::SaveToBinFile(char const *FileName)
{
roboczy->InfoSet(info + i);
file.write(reinterpret_cast<char *>(roboczy),
sizeof(TSubModel)); // zapis jednego submodelu
256); // zapis jednego submodelu
}
if (tra)
{ // zapis transformów
@@ -2110,7 +2134,7 @@ void TModel3d::SaveToBinFile(char const *FileName)
1); // ciąg o numerze zero nie jest używany, ma tylko znacznik końca
for (i = 0; i < iSubModelsCount; ++i)
if (info[i].iTextureLen)
file.write(info[i].pSubModel->pTexture, info[i].iTextureLen);
file.write(info[i].pSubModel->pTexture.c_str(), info[i].iTextureLen);
if ((-tex) & 3)
file.write(reinterpret_cast<char *>(&zero),
((-tex) & 3)); // wyrównanie do wielokrotności 4 bajtów
@@ -2122,7 +2146,7 @@ void TModel3d::SaveToBinFile(char const *FileName)
file.write(reinterpret_cast<char *>(&i), 4);
for (i = 0; i < iSubModelsCount; ++i)
if (info[i].iNameLen)
file.write(info[i].pSubModel->pName, info[i].iNameLen);
file.write(info[i].pSubModel->pName.c_str(), info[i].iNameLen);
if ((-nam) & 3)
file.write(reinterpret_cast<char *>(&zero),
((-nam) & 3)); // wyrównanie do wielokrotności 4 bajtów