J
Ich nochmal, sorry für Doppelpost
Ich wollte eigentlich nur präsentieren wie ich es letztendlich (fast komplett) gelöst habe, falls jemand auf diesen Post stößt.
Zunächst habe ich mir ein Array mit Eckpunkten der Bounding-Box definiert.
// (Array deklaratoin in Header-Datei)
// Defenition der Eckpunkte
eckpunkte[0] = glm::vec4(-1, 1,-1, 1);
eckpunkte[1] = glm::vec4( 1, 1,-1, 1);
eckpunkte[2] = glm::vec4( 1,-1,-1, 1);
eckpunkte[3] = glm::vec4(-1,-1,-1, 1);
eckpunkte[4] = glm::vec4(-1, 1, 1, 1);
eckpunkte[5] = glm::vec4( 1, 1, 1, 1);
eckpunkte[6] = glm::vec4( 1,-1, 1, 1);
eckpunkte[7] = glm::vec4(-1,-1, 1, 1);
Dann habe ich diese Eckpunkte mit meiner ModelView-Matrix verrechnet Um sie in den View-Space zu bringen. Um dies ohne weiteres zu können wurden die Daten auch in homogenen koordinaten angelegt (die 4te Komponente der Eckpunkte).
glm::mat4 modelView = this->viewport->getCamera()->getViewMatrix() * this->modelMatrix;
for(int i = 0; i < 8; i ++) {
modelView * eckpunkte[i];
}
Um nun zu bestimmen welches der Eckpunkte mit am nächsten an meinem View ist habe ich eine kleine minMax-Funktion geschrieben.
void minMax(int *minIndex, int *maxIndex, glm::vec4 *arr, int arrSize) {
*minIndex = 0;
*maxIndex = 0;
for(int i = 1; i < arrSize; i ++) {
cout << arr[i][2] << endl;
if(arr[i][2] < arr[*minIndex][2])
*minIndex = i;
if(arr[i][2] > arr[*maxIndex][2])
*maxIndex = i;
}
}
Jetzt laufe ich in einer Schleife von der Z-Position der als minIndex bestimmten ecke zur Z-Position der als maxIndex bestimmten Ecke.
for(GLfloat z = min + stepSize; z <= max; z = z + stepSize) {
// Schleife über alle Schichten
...
In der Schleife möchte ich bestimmen auf welchen Kanten (also zwischen welchen 2 Ecken meiner Bounding-Box) sich die aktuelle Z-Schicht befindet.
Dazu habe ich eine sehr einfache Funktion geschrieben, die gaaaaaanz sicher viel Optimierungspotential besitzt
void KLASSENNAME::getEdges(GLfloat zValue, int **edgeArray) {
int count = 0;
if(eckpunkte[0][2] <= zValue && eckpunkte[1][2] > zValue || eckpunkte[0][2] >= zValue && eckpunkte[1][2] < zValue) {
edgeArray[count][0] = 0;
edgeArray[count][1] = 1;
count++;
}
if(eckpunkte[1][2] <= zValue && eckpunkte[2][2] > zValue || eckpunkte[1][2] >= zValue && eckpunkte[2][2] < zValue) {
edgeArray[count][0] = 1;
edgeArray[count][1] = 2;
count++;
}
if(eckpunkte[2][2] <= zValue && eckpunkte[3][2] > zValue || eckpunkte[2][2] >= zValue && eckpunkte[3][2] < zValue) {
edgeArray[count][0] = 2;
edgeArray[count][1] = 3;
count++;
}
if(eckpunkte[0][2] <= zValue && eckpunkte[3][2] > zValue || eckpunkte[0][2] >= zValue && eckpunkte[3][2] < zValue) {
edgeArray[count][0] = 0;
edgeArray[count][1] = 3;
count++;
}
if(eckpunkte[4][2] <= zValue && eckpunkte[5][2] > zValue || eckpunkte[4][2] >= zValue && eckpunkte[5][2] < zValue) {
edgeArray[count][0] = 4;
edgeArray[count][1] = 5;
count++;
}
if(eckpunkte[5][2] <= zValue && eckpunkte[6][2] > zValue || eckpunkte[5][2] >= zValue && eckpunkte[6][2] < zValue) {
edgeArray[count][0] = 5;
edgeArray[count][1] = 6;
count++;
}
if(eckpunkte[6][2] <= zValue && eckpunkte[7][2] > zValue || eckpunkte[6][2] >= zValue && eckpunkte[7][2] < zValue) {
edgeArray[count][0] = 6;
edgeArray[count][1] = 7;
count++;
}
if(eckpunkte[4][2] <= zValue && eckpunkte[7][2] > zValue || eckpunkte[4][2] >= zValue && eckpunkte[7][2] < zValue) {
edgeArray[count][0] = 4;
edgeArray[count][1] = 7;
count++;
}
if(eckpunkte[0][2] <= zValue && eckpunkte[4][2] > zValue || eckpunkte[0][2] >= zValue && eckpunkte[4][2] < zValue) {
edgeArray[count][0] = 0;
edgeArray[count][1] = 4;
count++;
}
if(eckpunkte[5][2] <= zValue && eckpunkte[1][2] > zValue || eckpunkte[5][2] >= zValue && eckpunkte[1][2] < zValue) {
edgeArray[count][0] = 5;
edgeArray[count][1] = 1;
count++;
}
if(eckpunkte[2][2] <= zValue && eckpunkte[6][2] > zValue || eckpunkte[2][2] >= zValue && eckpunkte[6][2] < zValue) {
edgeArray[count][0] = 2;
edgeArray[count][1] = 6;
count++;
}
if(eckpunkte[3][2] <= zValue && eckpunkte[7][2] > zValue || eckpunkte[3][2] >= zValue && eckpunkte[7][2] < zValue) {
edgeArray[count][0] = 3;
edgeArray[count][1] = 7;
count++;
}
}
Auch hier wird wieder nur mit Indizes gearbeitet.
Hab ich alle Kanten gefunden durchlaufe ich sie mit einer Inneren-Schleife.
// edgeArray ist mit {-1, -1} vordefiniert, da -1 ein ungültiger Index ist.
while(edgeArray[i][0] != -1) {
Innerhalb dieser While-Schleife Berechne ich mit einer Geradengleichung die Position der X und Y koordinate auf der aktuellen Kante an position Z.
// Bestimmung des Richtungsvektors der Gradengleichung von der aktuellen Kante
glm::vec4 r = eckpunkte[edgeArray[i][0]] - eckpunkte[edgeArray[i][1]];
// Bestimmen des Wertes der Variablen der Gradengleichung anhand der z-koordinate
double k = -eckpunkte[edgeArray[i][1]][2] / r[2];
// Bestimmung von x und y
GLfloat x = r[0] + k * eckpunkte[edgeArray[i][1]][0];
GLfloat y = r[1] + k * eckpunkte[edgeArray[i][1]][1];
Alle so erstellten Vertices speicher ich in einer kleinen selbstgeschriebenen Struktur ab.
struct VerticesAndAngles {
bool operator<(const VerticesAndAngles & vaa) { return this->angle < vaa.angle; }
glm::vec3 vertice;
double angle;
};
Wie man an der Struktur schon erkennen kann berechne ich den Winkel zwischen den Punkten um die Vertices in Umgekehrter Uhrzeiger-Reihenfolge zu sortieren.
Das kann ich einfach so machen, da meine Schichten alle konvex sind.
EDIT:
Das zeichnen der Schichten mit OpenGL
Ich sammle alle Schichten in einem vectorglm::vec3 und Multipliziere jeder mit der Invertierten ModelView-Matrix (um sie wieder aus dem View-Space zurück zu rechnen, da sie später mit der MVP multipliziert werden).
Beim erzeugen habe ich mir in der Schleife über die schichten gemerkt, an welcher Stelle in meinem vector sie beginnen, und wie viele Vertices zu dieser Schicht gehören.
// Innerhalb der Schleife über alle Schichten
for(i = 0; i < vaaVec.size(); i ++) {
glm::vec4 erg = glm::inverse(modelView) * glm::vec4(vaaVec[i].vertice, 1);
vertices.push_back(glm::vec3(erg.x,erg.y,erg.z));
uvw.push_back(glm::vec3((erg.x+1)/2,(erg.y+1)/2,(erg.z+1)/2));
}
if(sliceCount == 0) {
startValues[0] = 0;
amountOfVertices[0] = vertices.size();
}
else {
startValues[sliceCount] = startValues[sliceCount-1] + amountOfVertices[sliceCount-1];
amountOfVertices[sliceCount] = vaaVec.size();
}
sliceCount++;
Nach dem ganzen Buffer-Binden usw gehe ich in einer Schleife über alle Schichten und rufe für jede Schicht ( also jeden Triangle-Fan den ich oben erzeugt habe) die glDrawArrays-Funktion auf.
for(int i = 0; i < amountOfSlices; i ++) {
glDrawArrays(GL_TRIANGLE_FAN, startValues[i], amountOfVertices[i]);
}
Die Werte die UVW's berechne ich mir ziemlich simpel. Da ich eine bounding-Box habe die von -1 bis 1 geht, und die UVW-Werte jeweils von 0-1 nehme ich einfach jeden x,y und z Wert eines Vertex, addiere ihn mit 1 und teile ihn daraufhin durch 2. So habe ich eine abbildung der Werte von -1 bis 1 auf die Werte 0 bis 1. Also eine Abbildung von xyz auf UVW. (Hab keine Ahnung ob das so klug ist, aber mirs nix besseres eingefallen und im Inet gefunden hab ich auch nix ^^).
Das führt auch zu ganz guten Ergebnissen. (Würds posten, wenn ich wüsste wo gratis ich Bilder uploaden kann ^^)
Jetzt muss ich nur nochn bisl mit dem Alpha-Blending rum spielen, da steig ich noch nicht so ganz durch.
Und herausfinden warum sich eine Manipulationen der Model-Matrix nur auf meine Textur bezieht, nicht aber auf die Bounding-Box.
Gruß
Jango