/src/Mesh.cpp
C++ | 479 lines | 273 code | 94 blank | 112 comment | 62 complexity | 4e3e86ebd6ed7882968ebe0c074ab7bd MD5 | raw file
- //------------------------------------//
- //
- // Mesh.cpp
- //
- // Author: ayufan (ayufan[at]o2.pl)
- // Project: ayuine2
- // Date: 2006-7-31
- //
- //------------------------------------//
-
- #include "StdAfx.hpp"
-
- namespace ayuine
- {
- //------------------------------------//
- // Mesh: Collection
-
- Collection<Mesh>::ObjectMap Collection<Mesh>::_objects;
-
- //------------------------------------//
- // MeshCollider: Enumeration
-
- static EnumValue ColliderTypeEnum[] = {
- {"none", mctNone},
- {"sphere", mctSphere},
- {"box", mctBox},
- {"convex", mctConvex},
- {"static", mctStatic},
- {"", 0}
- };
-
- //------------------------------------//
- // Mesh: Static Fields
-
- Property Mesh::Properties[] = {
- // Physics Fields
- Property(OffsetOf(Mesh, ColliderType), ColliderTypeEnum, "Collider"),
- Property(OffsetOf(Mesh, ColliderObject),ptBoolean, "ColliderObject"),
- Property(OffsetOf(Mesh, Density), ptValue, "Density"),
-
- // Render Fields
- Property(OffsetOf(Mesh, PRT), ptBoolean, "PRT"),
- Property()
- };
-
- //------------------------------------//
- // MeshVertex: Static Fields
-
- VertexDeclElement MeshVertex::Decl[] = {
- {0, OffsetOf(MeshVertex, Origin), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
- {0, OffsetOf(MeshVertex, Coords[0]),D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
- {0, OffsetOf(MeshVertex, Normal), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
- {0, OffsetOf(MeshVertex, Tangent), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
- D3DDECL_END()
- };
-
- //------------------------------------//
- // MeshSurface: Constructor
-
- MeshSurface::MeshSurface() {
- IndexStart = IndexCount = 0;
- }
-
- //------------------------------------//
- // MeshObject: Constructor
-
- MeshObject::MeshObject() {
- VertexStart = VertexCount = 0;
- IndexStart = IndexCount = 0;
- Frame = 0;
- }
-
- MeshObject::MeshObject(const MeshObject &oldObjectConst) {
- MeshObject &oldObject = const_cast<MeshObject&>(oldObjectConst);
-
- // Skopiuj i usuń stary obiekt
- memcpy(this, &oldObject, sizeof(MeshObject));
- memset(&oldObject, 0, sizeof(MeshObject));
- }
-
- //------------------------------------//
- // Mesh: Constructor
-
- Mesh::Mesh() {
- // Physics Fields
- ColliderType = mctNone;
- ColliderObject = false;
- Density = 1.0f;
- Mass = 0;
-
- // Render Fields
- PRT = false;
- }
-
- //------------------------------------//
- // Mesh: Destructor
-
- Mesh::~Mesh() {
-
- }
-
- //------------------------------------//
- // Mesh: Methods
-
- void Mesh::load(const string &name) {
- Engine::Log->print("Mesh: Loading %s...", name.c_str());
-
- // Zresetuj ustawienia
- ColliderType = mctNone;
- Mass = 10.0f;
-
- try {
- // Wczytaj mesha
- Reader reader(Engine::VFS->file(va("%s.cfg", name.c_str()), ftMesh).c_str());
-
- // Wczytaj podstawowe parametry
- reader.readProperties(Properties, this);
- }
- catch(Exception &e) {
- }
-
- // Spróbuj wczytać .mesh
- try {
- loadMesh(name);
- goto done;
- }
- catch(Exception &e) {
- }
-
- // Spróbuj wczytać .mesh (unigine)
- try {
- loadMeshU(name);
- goto done;
- }
- catch(Exception &e) {
- }
-
- // Spróbuj wczytać .obj
- try {
- loadObj(name);
- goto done;
- }
- catch(Exception &e) {
- }
-
- // Wypisz błąd
- Engine::Log->warning("Mesh: Couldn't load %s !", name.c_str());
-
- // Wyczyść bufory
- Vertices.clear();
- Indices.clear();
- Objects.clear();
-
- done:
- // Zainiciuj dane
- deviceReset(true);
- physicsReset();
- }
-
- void Mesh::loadMesh(const string &name) {
- // Otwórz plik z meshem
- SmartPtr<File> s(Engine::VFS->loadFile(va("%s.mesh", name.c_str()), ftMesh));
-
- // Wczytaj mesha
- *s << *this;
- _loaded = true;
- }
-
- void Mesh::save(const string &name) {
- Engine::Log->print("Mesh: Saving %s...", name.c_str());
-
- // Odtwórz plik do zapisu
- SmartPtr<File> s(Engine::VFS->saveFile(va("%s.mesh", name.c_str()), ftMesh));
-
- // Zapisz mesha
- *s << *this;
- }
-
- void Mesh::deviceReset(bool theBegin) {
- // Oznacz wszystkie materiały
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- for(u32 j = 0; j < object->Surfaces.size(); j++) {
- object->Surfaces.at(j).Material.cache();
- }
- if(Engine::Config->PRT && PRT) {
- object->PRT.cache();
- }
- }
-
- // Utwórz nowe bufory
- if(theBegin) {
- // Utwórz opis formatu wierzchołków
- VertexType.reset(new ayuine::VertexType(MeshVertex::Decl));
-
- // Utwórz nowy bufor wierzchołków
- if(Vertices.size()) {
- VertexBuffer.reset(new ayuine::VertexBuffer(Vertices.size(), sizeof(MeshVertex)));
- VertexBuffer->update(Vertices, Vertices.size());
- }
-
- // Utwórz nowy bufor indeksów
- if(Indices.size()) {
- IndexBuffer.reset(new ayuine::IndexBuffer(Indices.size(), if16, false));
- IndexBuffer->update(Indices, Indices.size());
- }
- }
- }
-
- void Mesh::deviceLost(bool theEnd) {
- // Zniszcz bufory
- if(theEnd) {
- // Zniszcz opis formatu wierzchołków
- VertexType.reset();
-
- // Zniszcz stary bufor wierzchołków
- VertexBuffer.reset();
-
- // Zniszcz stary bufor indeksów
- IndexBuffer.reset();
- }
- }
-
- void Mesh::physicsReset() {
- // Utwórz odpowiedniego collidera
- if(ColliderType == mctNone) {
- // Ustaw collidera
- Collider.reset(new NullCollider());
-
- if(ColliderObject) {
- // Zresetuj kolidery dla obiektów
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- // Zresetuj collidera
- object->Collider.reset(new NullCollider());
-
- // Oblicz masę
- object->Mass = 0;
- }
- }
-
- // Oblicz masę
- Mass = 0;
- }
- else if(ColliderType == mctStatic) {
- StaticCollider* collider = new StaticCollider();
-
- // Spróbuj wczytać collidera
- try {
- // Otwóz plik z colliderem
- SmartPtr<File> s(Engine::VFS->loadFile(va("%s.cld", name()), ftMesh));
-
- // Wczytaj collidera
- *s << *collider;
- goto done;
- }
- catch(Exception &e) {
- Engine::Log->warning("Mesh: Collider not found ! Building...");
- }
-
- // Rozpocznij budowanie collidera
- collider->begin();
- {
- Array<vec3> verts;
-
- // Dodaj każdą obiekt
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- // Sprawdź wszystkie powierzchnie
- for(u32 j = 0; j < object->Surfaces.size(); j++) {
- MeshSurface* surface = &object->Surfaces.at(j);
-
- // Sprawdź materiał
- if(!surface->Material || !surface->Material->collidable())
- continue;
-
- // Zmień rozmiar listy wierzchołków
- verts.resize(surface->IndexCount);
-
- // Dodaj wierzchołki materiału
- for(u32 k = 0; k < surface->IndexCount; k++) {
- verts.at(k) = Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + surface->IndexCount - 1 - k)).Origin;
- }
-
- // Dodaj ściankę do collidera
- if(verts.size()) {
- // Dodaj każdy trójkąt oddzielnie
- for(u32 k = 2; k < verts.size(); k += 3)
- collider->addFace(surface->Material->hash(), &verts.at(k - 2), 3);
- //collider->addFace(surface->Material->hash(), &verts[0], verts.size());
- }
- }
- }
- }
- // Zakończ budowanie collidera
- collider->end(false);
-
- // Zapisz collidera
- try {
- // Otwórz plik z colliderem
- SmartPtr<File> s(Engine::VFS->saveFile(va("%s.cld", name()), ftMesh));
-
- // Zapisz collidera
- *s << *collider;
- }
- catch(Exception &e) {
- Engine::Log->warning("Mesh: Can't save collider %s !", name());
- }
- done:
- // Ustaw collidera
- Collider.reset(collider);
-
- // Oblicz masę
- Mass = FLT_MAX;
- }
- else {
- Array<vec3> verts;
-
- // Zbuduj sferę
- if(ColliderObject) {
- Array<ayuine::Collider*> colliders;
-
- // Wyzeruj masę
- Mass = 0;
-
- // Zbuduj collidery dla każdego obiektu oddzielnie
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- // Wyczyść listę wierzchołków
- verts.reset();
-
- // Sprawdź wszystkie powierzchnie
- for(u32 j = 0; j < object->Surfaces.size(); j++) {
- MeshSurface* surface = &object->Surfaces.at(j);
-
- // Sprawdź materiał
- if(!surface->Material || !surface->Material->collidable())
- continue;
-
- // Dodaj wierzchołki materiału
- for(u32 k = 0; k < surface->IndexCount; k++) {
- verts.push(Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + k)).Origin);
- }
- }
-
- // Utwórz collidera
- if(verts.empty()) {
- object->Collider.reset(new NullCollider());
-
- // Ustaw masę
- object->Mass = 0;
- }
- else {
- if(ColliderType == mctSphere) {
- bsphere sphere;
-
- // Oblicz sferę
- sphere.assign(&verts[0], verts.size());
-
- // Utwórz collidera
- object->Collider.reset(new SphereCollider(sphere));
- }
- else if(ColliderType == mctBox) {
- bbox box;
-
- // Oblicz sferę
- box.assign(&verts[0], verts.size());
-
- // Utwórz collidera
- object->Collider.reset(new BoxCollider(box));
- }
- else if(ColliderType == mctConvex) {
- // Utwórz collidera
- object->Collider.reset(new ConvexCollider(&verts[0], verts.size()));
- }
- else {
- Assert("Invalid ColliderType" && false);
- }
-
- // Oblicz masę
- object->Mass = Density * object->Collider->Volume;
-
- // Dodaj masę
- Mass += object->Mass;
-
- // Dodaj collidera do listy
- colliders.push(object->Collider);
- }
- }
-
- // Utwórz collidera złożonego z colliderów pojedyńczych obiektów
- if(colliders.empty()) {
- Collider.reset(new NullCollider());
- }
- else {
- Collider.reset(new CompoundCollider(colliders));
- }
- }
- else {
- // Zbuduj collidery dla całego mesha
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- // Wyczyść listę wierzchołków
- verts.reset();
-
- // Sprawdź wszystkie powierzchnie
- for(u32 j = 0; j < object->Surfaces.size(); j++) {
- MeshSurface* surface = &object->Surfaces.at(j);
-
- // Sprawdź materiał
- if(!surface->Material || !surface->Material->collidable())
- continue;
-
- // Dodaj wierzchołki materiału
- for(u32 k = 0; k < surface->IndexCount; k++) {
- verts.push(Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + k)).Origin);
- }
- }
- }
-
- // Utwórz collidera
- if(verts.empty()) {
- Collider.reset(new NullCollider());
-
- // Ustaw masę
- Mass = 0;
- }
- else {
- if(ColliderType == mctSphere) {
- bsphere sphere;
-
- // Oblicz sferę
- sphere.assign(&verts[0], verts.size());
-
- // Utwórz collidera
- Collider.reset(new SphereCollider(sphere));
- }
- else if(ColliderType == mctBox) {
- bbox box;
-
- // Oblicz sferę
- box.assign(&verts[0], verts.size());
-
- // Utwórz collidera
- Collider.reset(new BoxCollider(box));
- }
- else if(ColliderType == mctConvex) {
- // Utwórz collidera
- Collider.reset(new ConvexCollider(&verts[0], verts.size()));
- }
- else {
- Assert("Invalid ColliderType" && false);
- }
-
- // Oblicz masę
- Mass = Density * Collider->Volume;
- }
- }
- }
- }
-
- void Mesh::physicsLost() {
- // Zniszcz głównego collidera
- Collider.reset();
-
- // Zniszcz collidera dla każdego obiektu
- for(u32 i = 0; i < Objects.size(); i++) {
- MeshObject* object = &Objects.at(i);
-
- // Zresetuj collidera
- object->Collider.reset();
- }
- }
- };