#include "Model3D.h" #include "Model2D.h" #include "DXBuffer.h" #include "Textur.h" #include "Animation3D.h" #include "Welt3D.h" #include "Textur.h" #include "Bild.h" #ifdef WIN32 #include #endif #include using namespace Framework; // Inhalt der Knochen Klasse // Konstruktor Knochen::Knochen(int id) { pos = Vec3< float >(0, 0, 0); winkel = Vec3< float >(0, 0, 0); geschwister = 0; kinder = 0; this->id = id; } // Destruktor Knochen::~Knochen() { delete geschwister; delete kinder; } // public // Setzt die Position des Knochens relativ zum Model Ursprung // pos: Die Position void Knochen::setPosition(Vec3< float >& pos) { this->pos = pos; } // Setzt die Drehung des Knochens relativ zum Model Ursprung // winkel: Ein Vektor der die Drehung um die verschiedenen Achsen als Komponenten hat void Knochen::setDrehung(Vec3< float >& winkel) { this->winkel = winkel; } // Fügt dem Knochen ein Geschwister Knochen hinzu // k: Der Knochen, der hinzugefügt werden soll void Knochen::addGeschwisterKnochen(Knochen* k) { if (!geschwister) geschwister = k; else geschwister->addGeschwisterKnochen(k); } // Fügt einem bestimmten Knochen ein Kind Knochen hinzu // id: Die id des Knochens, wo der Knochen als Kind hinzugefügt werden soll // k: Der Knochen, der hinzugefügt werden soll void Knochen::addKind(int id, Knochen* k) { if (this->id == id) { if (!kinder) kinder = k; else kinder->addGeschwisterKnochen(k); } else { if (kinder) kinder->addKind(id, k); else { Text err = "Es wurde kein Knochen mit der Id: "; err += id; err += " im Skelett gefunden, um ein Kind Knochen hinzuzufügen. Datei:" __FILE__ ", Zeile: "; err += __LINE__; err += "!"; delete k; throw std::out_of_range((const char*)err); } } } // Berechnet die Matrizen des Knochen und die von all seinen Geschwister Knochen und Kind Knochen // elternMat: Die fertig berechnete Matrix des Elternknochens // matBuffer: Ein Array, in dem alle berechneten Matrizen gespeichert werden sollen // scaleFactor: Die Skallierung des Modells // kamMatrix: Die vereiniegung der view und projektions Matrizen void Knochen::kalkulateMatrix(Mat4< float >& elternMat, Mat4< float >* matBuffer, float scaleFactor, Mat4< float >& kamMat) { if (geschwister) geschwister->kalkulateMatrix(elternMat, matBuffer, scaleFactor, kamMat); matBuffer[id] = matBuffer[id].translation(pos * scaleFactor) * matBuffer[id].rotationZ(winkel.z) * matBuffer[id].rotationX(winkel.x) * matBuffer[id].rotationY(winkel.y) * matBuffer[id].scaling(scaleFactor); matBuffer[id] = elternMat * matBuffer[id]; if (kinder) kinder->kalkulateMatrix(matBuffer[id], matBuffer, scaleFactor, kamMat); matBuffer[id] = kamMat * matBuffer[id]; } Knochen* Framework::Knochen::zGeschwister() const { return geschwister; } Knochen* Framework::Knochen::zKind() const { return kinder; } // Kopiert den Knochen mit allen Geschwister Knochen und Kind Knochen Knochen* Knochen::kopiereKnochen() const { Knochen* ret = new Knochen(id); ret->pos = pos; ret->winkel = winkel; if (geschwister) ret->geschwister = geschwister->kopiereKnochen(); if (kinder) ret->kinder = kinder->kopiereKnochen(); return ret; } // Gibt die Id des Knochens zurück int Knochen::getId() const { return id; } // Gibt die Drehung des Knochens zurück Vec3< float > Knochen::getDrehung() const { return winkel; } // Gibt die Position des Knochens zurück Vec3< float > Knochen::getPosition() const { return pos; } // Gibt den Radius des Knochens zurück float Knochen::getRadius() const { float r = pos.getLength(); if (geschwister) r = MAX(r, geschwister->getRadius()); if (kinder) r += kinder->getRadius(); return r; } // Inhalt der Skelett Klasse // Konstruktor Skelett::Skelett() : ReferenceCounter() { k = 0; nextId = 0; } // Destruktor Skelett::~Skelett() { if (k) delete k; } // Gibt die Id des nächsten Knochens zurück und berechnet die neue Id für den Knochen danach // Es können maximal MAX_KNOCHEN_ANZ Knochen für ein Skelett existieren. Wenn diese Zahl überschritten wird, so wird -1 zurückgegeben int Skelett::getNextKnochenId() { return nextId++; } void Framework::Skelett::setNextKnochenId(int id) { nextId = id; } // Fügt dem Skellet einen Knochen hinzu // k: Der Knochen // elternId: Die Id des Eltern Knochens. Wenn der Knochen kein Elternknochen besitzt, kannder Parameter weggelassen werden. void Skelett::addKnochen(Knochen* k, int elternId) { if (!this->k) this->k = k; else this->k->addKind(elternId, k); if (k->getId() >= nextId) nextId = k->getId() + 1; } // Berechnet die Matrizen der Knochen // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird // scaleFactor: Die skallierung des Objektes // kamMatrix: Die vereiniegung der view und projektions Matrizen // return: gibt die Anzahl der verwendeten Matrizen zurück int Skelett::kalkulateMatrix(Mat4< float >& modelMatrix, Mat4< float >* matBuffer, float scaleFactor, Mat4< float >& kamMatrix) { k->kalkulateMatrix(modelMatrix, matBuffer, scaleFactor, kamMatrix); return nextId; } // Berechnet den Radius des Skeletts float Skelett::getRadius() const { if (k) return k->getRadius(); return 0; } // gibt den Wurzel Knochen zurück Knochen* Framework::Skelett::zKnochen() const { return k; } // Kopiert das Skelett Skelett* Skelett::kopiereSkelett() const { Skelett* ret = new Skelett(); ret->nextId = nextId; if (k) ret->addKnochen(k->kopiereKnochen()); return ret; } int Framework::Skelett::zNextKnochenId() const { return nextId; } // Inhalt des Polygon3D Struct // Konstruktor Polygon3D::Polygon3D() { indexAnz = 0; indexList = 0; } // Destruktor Polygon3D::~Polygon3D() { delete[] indexList; } // Inhalt der Model3DData Klasse // Konstruktor Model3DData::Model3DData(DXBuffer* dxVertexBuffer, DXBuffer* dxIndexBuffer, int id) : ReferenceCounter(), dxIndexBuffer(dxIndexBuffer), dxVertexBuffer(dxVertexBuffer), id(id) { skelett = 0; vertexList = 0; vertexCount = 0; polygons = new Array< Polygon3D* >(); ambientFactor = 1.f; diffusFactor = 0.f; specularFactor = 0.f; indexCount = 0; indexBuffer = 0; radius = 0; } // Destruktor Model3DData::~Model3DData() { clearModel(); polygons->release(); dxIndexBuffer->release(); dxVertexBuffer->release(); delete[] indexBuffer; } // updates the DX Buffer gpu memory if changed DLLEXPORT void Model3DData::updateGPUMemory() { dxIndexBuffer->copieren(); dxVertexBuffer->copieren(); } // Löscht alle Model daten void Model3DData::clearModel() { delete[] vertexList; vertexCount = 0; vertexList = 0; for (Polygon3D* i : *polygons) delete i; polygons->leeren(); if (skelett) skelett->release(); skelett = 0; radius = 0; delete[] indexBuffer; indexBuffer = 0; indexCount = 0; } // Berechnet die normalen für die Eckpunkte des Modells void Model3DData::calculateNormals() { for (int i = 0; i < vertexCount; i++) { Vec3< float > normal(0, 0, 0); for (Polygon3D* p : *polygons) { int begin = 0; for (int j = 0; j < p->indexAnz; j++) { if (j % 3 == 0) begin = j; if (p->indexList[j] == i) { Vec3< float > a = vertexList[p->indexList[begin]].pos; Vec3< float > b = vertexList[p->indexList[begin + 1]].pos; Vec3< float > c = vertexList[p->indexList[begin + 2]].pos; normal += (b - a).crossProduct(c - a).normalize(); normal.normalize(); } } } vertexList[i].normal = normal; } } //! Erstellt einen buffer für alle polygon indizes void Model3DData::buildIndexBuffer() { delete[] indexBuffer; indexCount = 0; for (Polygon3D* p : *polygons) indexCount += p->indexAnz; indexBuffer = new int[indexCount]; int current = 0; for (Polygon3D* p : *polygons) { memcpy(indexBuffer + current, p->indexList, sizeof(int) * p->indexAnz); current += p->indexAnz; } dxIndexBuffer->setLength((int)(indexCount * sizeof(int))); dxIndexBuffer->setData(indexBuffer); } // Setzt den Zeiger auf ein standartmäßig verwendete Skelett // s: Das Skelett, das verwendet werden soll void Model3DData::setSkelettZ(Skelett* s) { if (skelett) skelett->release(); skelett = s; } // Setzt einen Zeiger auf eine Liste mit allen Vertecies des Models // vertexList: Ein Array mit Vertecies // anz: Die Anzahl der Vertecies im Array void Model3DData::setVertecies(Vertex3D* vertexList, int anz) { delete[] this->vertexList; this->vertexList = vertexList; vertexCount = anz; maxPos = { -INFINITY, -INFINITY, -INFINITY }; minPos = { INFINITY, INFINITY, INFINITY }; radius = 0; for (int i = 0; i < anz; i++) { float r = vertexList[i].pos.getLength(); if (r > radius) radius = r; if (vertexList[i].pos.x < minPos.x) minPos.x = vertexList[i].pos.x; if (vertexList[i].pos.y < minPos.y) minPos.y = vertexList[i].pos.y; if (vertexList[i].pos.z < minPos.z) minPos.z = vertexList[i].pos.z; if (vertexList[i].pos.x > maxPos.x) maxPos.x = vertexList[i].pos.x; if (vertexList[i].pos.y > maxPos.y) maxPos.y = vertexList[i].pos.y; if (vertexList[i].pos.z > maxPos.z) maxPos.z = vertexList[i].pos.z; vertexList[i].id = i; } dxVertexBuffer->setLength((int)(anz * sizeof(Vertex3D))); dxVertexBuffer->setData(vertexList); } // Fügt ein Polygon zum Model hinzu // polygon: Das Polygon, das hinzugefügt erden soll void Model3DData::addPolygon(Polygon3D* polygon) { polygons->add(polygon); buildIndexBuffer(); } // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Model3DData::setAmbientFactor(float f) { ambientFactor = f; } // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Model3DData::setDiffusFactor(float f) { diffusFactor = f; } // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Model3DData::setSpecularFactor(float f) { specularFactor = f; } // Konvertiert ein 2d Model zu 3D // model: Das 2d Model, das zu 3d konvertiert werden soll // z: Die z koordinate aller punkte des Models void Model3DData::copyModel2D(Model2DData* model, float z) { if (model && model->vListen && model->polygons) { clearModel(); int vAnz = 0; for (const Polygon2D& p : *model->polygons) vAnz += p.vertex->getEintragAnzahl(); Vertex3D* vertexList = new Vertex3D[vAnz]; int index = 0; for (auto i : *model->vListen) { Polygon3D* p = new Polygon3D(); p->indexAnz = 0; for (auto j : *i) { for (auto k = j->zListe()->begin(); k && k.hasNext() && k.next().hasNext(); k++) p->indexAnz += 3; } p->indexList = new int[p->indexAnz]; p->indexAnz = 0; for (auto j : *i) { for (auto k = j->zListe()->begin(); k; k++) { assert(index < vAnz); if (index < vAnz) { vertexList[index].pos = Vec3< float >(k->punkt->x, k->punkt->y, z); vertexList[index].tPos = (Vec2< float >) * k->textur; if (k.hasNext() && k.next().hasNext()) { p->indexList[p->indexAnz] = index; p->indexAnz++; p->indexList[p->indexAnz] = index + 1; p->indexAnz++; p->indexList[p->indexAnz] = index + 2; p->indexAnz++; } } else break; index++; } } addPolygon(p); } this->setVertecies(vertexList, vAnz); buildIndexBuffer(); calculateNormals(); } } // Entfernt ein Polygon // index: Der Index des Polygons void Model3DData::removePolygon(int index) { if (!polygons->hat(index)) return; delete polygons->get(index); polygons->remove(index); buildIndexBuffer(); } // Berechnet die Matrizen der Knochen // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird // scaleFactor: Die Skallierung des Modells // kamMatrix: Die vereiniegung der view und projektions Matrizen // return: gibt die Anzahl der verwendeten Matrizen zurück int Model3DData::kalkulateMatrix(Mat4< float >& modelMatrix, Mat4< float >* matBuffer, float scaleFactor, Mat4< float >& kamMatrix) const { if (!skelett) return 0; return skelett->kalkulateMatrix(modelMatrix, matBuffer, scaleFactor, kamMatrix); } // Gibt die Anzahl an Polygonen zurück int Model3DData::getPolygonAnzahl() const { return polygons->getEintragAnzahl(); } // Gibt ein bestimmtes Polygon zurück // index: Der Index des Polygons Polygon3D* Model3DData::getPolygon(int index) const { if (!polygons->hat(index)) return 0; return polygons->get(index); } // Gibt einen Iterator zurück, mit dem sich die Polygons auflisten lassen Iterator< Polygon3D* > Model3DData::getPolygons() const { return polygons->begin(); } // Gibt den radius einer Kugel zurück, die das gesammte Model umschließt float Model3DData::getRadius() const { return radius; } // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister()) int Model3DData::getId() const { return id; } // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird float Model3DData::getAmbientFactor() const { return ambientFactor; } // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird float Model3DData::getDiffusFactor() const { return diffusFactor; } // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird float Model3DData::getSpecularFactor() const { return specularFactor; } // Gibt eine Kopie des Skeletts zurück, welches für annimationen verwendet werden kann Skelett* Model3DData::copySkelett() const { return skelett ? skelett->kopiereSkelett() : 0; } // Gibt die Anzahl an Vertices zurück int Model3DData::getVertexAnzahl() const { return vertexCount; } // Gibt einen Buffer mit allen Vertecies des Models zurück const Vertex3D* Model3DData::zVertexBuffer() const { return vertexList; } //! Gibt eine refferenz auf den beginn des indexBuffers zurück const int* Model3DData::getIndexBuffer() const { return indexBuffer; } //! Gibt eine die Anzahl der indizes im indexBuffer zurück int Model3DData::getIndexCount() const { return indexCount; } //! Gibt den Index buffer zurück; DXBuffer* Model3DData::zDXIndexBuffer() const { return dxIndexBuffer; } //! Gibt den Vertex buffer zurück; DXBuffer* Model3DData::zDXVertexBuffer() const { return dxVertexBuffer; } //! gibt den minnimalen Punkt der Bounding box des Models zurück Vec3 Model3DData::getMinPos() const { return minPos; } //! gibt den maximalen Punkt der bounding box des Mopdels zurück Vec3 Model3DData::getMaxPos() const { return maxPos; } // Inhalt der Model3DTextur // Konstruktor Model3DTextur::Model3DTextur() : ReferenceCounter() { textures = new Textur * [1]; textures[0] = 0; textureCount = 1; } // Destruktor Model3DTextur::~Model3DTextur() { for (int i = 0; i < textureCount; i++) { if (textures[i]) textures[i]->release(); } delete[] textures; } // Legt fest, welche Textur für welches Polygon ist // pI: Der Index des Polygons // txt: Die Textur des Polygons void Model3DTextur::setPolygonTextur(int pI, Textur* txt) { if (pI >= textureCount) { Textur** tmp = textures; textures = new Textur * [pI + 1]; memcpy(textures, tmp, sizeof(Textur*) * textureCount); memset(textures + textureCount, 0, sizeof(Textur*) * (pI + 1 - textureCount)); delete[] tmp; textureCount = pI + 1; } if (textures[pI]) textures[pI]->release(); textures[pI] = txt; } // Gibt einen Zeiger auf die Textur eines Polygons zurück ohne erhöhten Reference Counter // i: Der Index des Polygons Textur* Model3DTextur::zPolygonTextur(int i) const { return textures[i]; } // Inhalt der AnimationData Struktur Model3D::AnimationData* Model3D::AnimationData::getThis() { return this; } Model3D::AnimationData* Model3D::AnimationData::release() { a->release(); delete this; return 0; } // Inhalt der Model3D Klasse // Konstruktor Model3D::Model3D() : Zeichnung3D() { model = 0; textur = 0; skelett = 0; animations = new RCArray< AnimationData >(); ambientFactor = 1.f; diffusFactor = 0.f; specularFactor = 0.f; } // Destruktor Model3D::~Model3D() { if (model) model->release(); if (textur) textur->release(); if (skelett) skelett->release(); animations->release(); } // Fügt eine Animation hinzu // a: Die neue Animation void Model3D::addAnimation(Animation3D* a, double speed) { AnimationData* d = new AnimationData(); d->a = a; d->speed = speed; d->offset = 0; animations->add(d); } // Entfernt eine Animation // zA: Die zu entfernende Animation void Model3D::removeAnimation(Animation3D* zA) { for (int i = 0; i < animations->getEintragAnzahl(); i++) { if (animations->z(i)->a == zA) { animations->remove(i); return; } } } // Setzt die Daten des Models // data: Die Daten void Model3D::setModelDaten(Model3DData* data) { if (model) model->release(); if (skelett) skelett = (Skelett*)skelett->release(); model = data; if (model) { skelett = model->copySkelett(); this->ambientFactor = model->getAmbientFactor(); this->specularFactor = model->getSpecularFactor(); this->diffusFactor = model->getDiffusFactor(); } } // Setzt die zum Zeichnen zu benutzenden Texturen // txt: Ein Liste mit Texturen zu den verschiedenen Polygonen zugeordnet void Model3D::setModelTextur(Model3DTextur* txt) { if (textur) textur->release(); textur = txt; } // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Framework::Model3D::setAmbientFactor(float f) { this->ambientFactor = f; } // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Framework::Model3D::setDiffusFactor(float f) { diffusFactor = f; } // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1) void Framework::Model3D::setSpecularFactor(float f) { specularFactor = f; } // Errechnet die Matrizen aller Knochen des Skeletts des Models // viewProj: Die miteinander multiplizierten Kameramatrizen // matBuffer: Ein Array mit Matrizen, der gefüllt werden soll // return: Die Anzahl der Matrizen, die das Model benötigt int Model3D::errechneMatrizen(Mat4< float >& viewProj, Mat4< float >* matBuffer) { int ret = 0; if (skelett) ret = skelett->kalkulateMatrix(welt, matBuffer, size, viewProj); else if (model) ret = model->kalkulateMatrix(welt, matBuffer, size, viewProj); if (!ret) return Zeichnung3D::errechneMatrizen(viewProj, matBuffer); return ret; } // Verarbeitet die vergangene Zeit // tickval: Die zeit in sekunden, die seit dem letzten Aufruf der Funktion vergangen ist // return: true, wenn sich das Objekt verändert hat, false sonnst. bool Model3D::tick(double tickval) { radius = model ? model->getRadius() : 0; if (skelett) { radius += skelett->getRadius(); for (auto i = animations->begin(); i && i._; i++) { rend = i->speed > 0; i->a->apply(skelett, i->offset, tickval * i->speed); } } return Zeichnung3D::tick(tickval); } //! zum aktualisieren der shader daten void Model3D::beforeRender(GraphicsApi* api, Shader* zVertexShader, Shader* zPixelShader) {} void Model3D::afterRender(GraphicsApi* api, Shader* zVertexShader, Shader* zPixelShader) {} // Gibt die Textur zurück Model3DTextur* Model3D::getTextur() { return textur ? dynamic_cast(textur->getThis()) : 0; } // Gibt die Textur zurück (ohne erhöhten Reference Counter) Model3DTextur* Model3D::zTextur() { return textur; } // Gibt die ModelDaten zurück Model3DData* Model3D::getModelData() { return model ? dynamic_cast(model->getThis()) : 0; } // Gibt die ModelDaten zurück (ohne erhöhten Reference Counter) Model3DData* Model3D::zModelData() { return model; } // prüft, ob ein Strahl dieses Objekt trifft // point: der startpunkt des Strahls in Weltkoordinaten // dir: die Richtung des Strahls in Weltkoordinaten // maxSqDist: Die maximale quadratische distanz die erlaubt ist // pId: die Id des Polygons, zu dem der Schnittpunkt gehört // return: den quadratischen Abstand des Schnittpunktes zum Ursprung des Strahls oder -1, wenn kein schnittpunkt existiert float Model3D::traceRay(Vec3< float >& p, Vec3< float >& d, float maxSqDist, int& pId) const { if (!model) return -1; Vec3< float > dir = d; dir.rotateY(-angle.y); dir.rotateX(-angle.x); dir.rotateZ(-angle.z); Vec3< float > point = p; point.rotateY(-angle.y); point.rotateX(-angle.x); point.rotateZ(-angle.z); point -= pos; float nearest = (-dir.x * point.x - dir.y * point.y - dir.z * point.z) / (dir.x * dir.x + dir.y * dir.y + dir.z * dir.z); float dist = (point + dir * nearest).getLengthSq(); if (dist > (radius * size) * (radius * size) || (dir * nearest).getLength() - radius * size > sqrt(maxSqDist) || (nearest < 0 && (dir * nearest).getLengthSq() > radius * size * radius * size)) // es gibt kein schnittpunkt return -1; bool existsHit = 0; if (skelett) { // todo } else { int index = 0; for (auto p = model->getPolygons(); p; p++) { for (int j = 0; j < p->indexAnz; j++) { if (j % 3 == 0) { Vec3< float > a = model->zVertexBuffer()[p->indexList[j]].pos; Vec3< float > b = model->zVertexBuffer()[p->indexList[j + 1]].pos; Vec3< float > c = model->zVertexBuffer()[p->indexList[j + 2]].pos; Vec3< float > normal = (b - a).crossProduct(c - a).normalize(); if (normal * dir < 0) // Prüfe ob die Normale in Richtung des Strahl ursprungs zeigt { nearest = (a * normal - point * normal) / (dir * normal); Vec3< float > hit = point + dir * nearest; if ((b - a).angle(hit - a) <= (b - a).angle(c - a) && (c - a).angle(hit - a) <= (b - a).angle(c - a) && (a - b).angle(hit - b) <= (a - b).angle(c - b)) { maxSqDist = (hit - point).getLengthSq(); pId = index; existsHit = 1; } } index++; } } } } return existsHit ? maxSqDist : -1; } // berechnet die Farbe des Schnittpunktes deines Strahls // point: der startpunkt des Strahls in Weltkoordinaten // dir: die Richtung des Strahls in Weltkoordinaten // zWelt: die Welt, aus der der Strahl kommt // return: die Farbe des Schnittpunktes int Model3D::traceRay(Vec3< float >& p, Vec3< float >& d, int pId, Welt3D* zWelt) const { Vec3< float > dir = d; dir.rotateY(-angle.y); dir.rotateX(-angle.x); dir.rotateZ(-angle.z); Vec3< float > point = p; point.rotateY(-angle.y); point.rotateX(-angle.x); point.rotateZ(-angle.z); point -= pos; int index = 0; for (auto p = model->getPolygons(); p; p++, index++) { for (int j = 0; j < p->indexAnz; j++) { if (j % 3 == 0) { if (pId == 0) { const Vec3< float >& a = model->zVertexBuffer()[p->indexList[j]].pos; const Vec3< float >& b = model->zVertexBuffer()[p->indexList[j + 1]].pos; const Vec3< float >& c = model->zVertexBuffer()[p->indexList[j + 2]].pos; Vertex at = model->zVertexBuffer()[p->indexList[j]].tPos; Vertex bt = model->zVertexBuffer()[p->indexList[j + 1]].tPos; Vertex ct = model->zVertexBuffer()[p->indexList[j + 2]].tPos; Vec3< float > normal = (b - a).crossProduct(c - a).normalize(); float t = (a * normal - point * normal) / (dir * normal); Vec3< float > hit = point + dir * t; float a0 = (a - b).crossProduct(a - c).getLength() / 2; float a1 = (b - hit).crossProduct(c - hit).getLength() / 2 / a0; float a2 = (c - hit).crossProduct(a - hit).getLength() / 2 / a0; float a3 = (a - hit).crossProduct(b - hit).getLength() / 2 / a0; Vertex ht = at * a1 + bt * a2 + ct * a3; Bild* tex = textur->zPolygonTextur(index)->zBild(); if (ht.x >= 0 && ht.y >= 0 && ht.x <= 1 && ht.y <= 1) return tex->getPixel((int)(ht.x * ((float)tex->getBreite() - 1.f) + 0.5f), (int)(ht.y * ((float)tex->getHeight() - 1.f) + 0.5f)); return 0xFF000000; } pId--; } } } return 0xFF000000; } // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister()) int Model3D::getDatenId() const { return model ? model->getId() : -1; } // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird float Model3D::getAmbientFactor() const { return ambientFactor; } // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird float Model3D::getDiffusFactor() const { return diffusFactor; } // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird float Model3D::getSpecularFactor() const { return specularFactor; } // Gibt die Anzahl an Vertices zurück int Model3D::getVertexAnzahl() const { return model ? model->getVertexAnzahl() : 0; } // Gibt einen Buffer mit allen Vertecies des Models zurück const Vertex3D* Model3D::zVertexBuffer() const { return model ? model->zVertexBuffer() : 0; } //! Gibt true zurück wenn ein bestimmtes polygon gezeichnet werden muss bool Model3D::needRenderPolygon(int index) { return 1; } Textur* Model3D::zEffectTextur() { return 0; } float Model3D::getEffectPercentage() { return 0; }