Seite 1 von 1

Assimp .3ds modelle für OpenGL importieren

Verfasst: 13.01.2012, 18:45
von madmoses
Hi,

ich habe es geschaft mit wenig aufwand eine .3ds Datei in mein Programm zu laden. Leider habe ich das Problem
das meine Objekte alle um die x oder z achse (OpenGL Koordinaten System) um 90 grad gedreht sind. Kann ich Assimp irgendwie
sagen das ich die Objekte anders haben möchte? Also in OpenGL Style oder muss ich das manuell wieder in meinem Code zu recht drehen?

Danke :=)

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 14.01.2012, 10:48
von Aramis
Prinzipiell sollte die Ausrichtung von 3DS-Modellen richtig sein, vorausgesetzt, die Modelle waren in der Quelldatei richtig herum :-)

Gibst du evtl das ConvertToLeftHanded-Flag an? Sollte prinzipiell fuer OpenGl nicht noetig sein.

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 14.01.2012, 12:33
von kimmi
Setzt du auch die entsprechende Transformation aus dem Modell? Ich habe das gern immer mal vergessen.

Gruß Kimmi

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 16.01.2012, 15:22
von madmoses
Also meine Import Funktion sieht so aus:

Code: Alles auswählen

void AllRoundObject::DoTheImportThing()
{
  // Create an instance of the Importer class
  Assimp::Importer importer;

  // And have it read the given file with some example postprocessing
  // Usually - if speed is not the most important aspect for you - you'll
  // propably to request more postprocessing than we do in this example.
  scene = importer.ReadFile( this->pFile,
        aiProcess_CalcTangentSpace       |
        aiProcess_Triangulate            |
        aiProcess_JoinIdenticalVertices  | aiProcess_FlipWindingOrder |
        aiProcess_SortByPType);

  cout << "Load " << this->pFile << " ";
  // If the import failed, report it
  if( !scene)
  {
    cout << ( importer.GetErrorString())<< endl;
  }
  else
  {
	  cout << "SUCCESSFUL" << endl;
  }


  	  aiMesh** meshes = scene->mMeshes;

  	  numVertices = 0;
  	  numFaces = 0;
  	  unsigned int start_index = 0;
  	  unsigned int start_index_faces = 0;
  	  unsigned int old_faces = 0;
  	  cout << "Anzahl Meshes: " << scene->mNumMeshes << endl;


  	  for(unsigned int nMeshes = 0; nMeshes < scene->mNumMeshes; nMeshes++)
  	  {
  		  numVertices +=meshes[nMeshes]->mNumVertices;
  		  numFaces += meshes[nMeshes]->mNumFaces;

  	  }
  	  cout << numFaces << " " << numVertices << endl;
  	  //Für jedes Mesh die Vertices und Faces kopieren
  	  this->vertices = new Vertices[numVertices];
  	  this->normales = new Vertices[numVertices];
  	  this->faces = new Faces[numFaces];
  	  GLfloat min_x = 0, max_x = 0,
  	  	  	  min_y = 0, max_y = 0,
  	  	  	  min_z = 0, max_z = 0;

  	  for(unsigned int nMeshes = 0; nMeshes < scene->mNumMeshes; nMeshes++)
  	  {
  		  cout << "Mesh: " << nMeshes << endl;
  		  //Alles Vertices Kopieren in meine Struktur
  		  for(unsigned int nVertex = 0; nVertex < meshes[nMeshes]->mNumVertices; nVertex++)
  		  {
  			vertices[start_index].X = meshes[nMeshes]->mVertices[nVertex].x;
  			vertices[start_index].Y = meshes[nMeshes]->mVertices[nVertex].y;
  			vertices[start_index].Z = meshes[nMeshes]->mVertices[nVertex].z;
  			if(meshes[nMeshes]->mVertices[nVertex].x< min_x) min_x = meshes[nMeshes]->mVertices[nVertex].x;
  			if(meshes[nMeshes]->mVertices[nVertex].y< min_y) min_y = meshes[nMeshes]->mVertices[nVertex].y;
  			if(meshes[nMeshes]->mVertices[nVertex].z< min_z) min_z = meshes[nMeshes]->mVertices[nVertex].z;

  			if(meshes[nMeshes]->mVertices[nVertex].x > max_x) max_x = meshes[nMeshes]->mVertices[nVertex].x;
  			if(meshes[nMeshes]->mVertices[nVertex].y > max_y) max_y = meshes[nMeshes]->mVertices[nVertex].y;
  			if(meshes[nMeshes]->mVertices[nVertex].z > max_z) max_z = meshes[nMeshes]->mVertices[nVertex].z;

  			normales[start_index].X = meshes[nMeshes]->mNormals[nVertex].x;
  			normales[start_index].Y = meshes[nMeshes]->mNormals[nVertex].y;
  			normales[start_index].Z = meshes[nMeshes]->mNormals[nVertex].z;
  			start_index++;
  		  }
  		  //cout << "############## FACES ################" << endl;
  		  for(unsigned int nFaces = 0;  nFaces < meshes[nMeshes]->mNumFaces; nFaces++)
  		  {
  			  //cout << meshes[nMeshes]->mFaces[nFaces].mIndices[0] << " " <<  endl;
  			  faces[start_index_faces].X = meshes[nMeshes]->mFaces[nFaces].mIndices[0] + old_faces;
  			  faces[start_index_faces].Y = meshes[nMeshes]->mFaces[nFaces].mIndices[1] + old_faces;
  			  faces[start_index_faces].Z = meshes[nMeshes]->mFaces[nFaces].mIndices[2] + old_faces;
  			  start_index_faces++;
  		  }
  		  old_faces = start_index;
  	  }
kimmi hat geschrieben:Setzt du auch die entsprechende Transformation aus dem Modell? Ich habe das gern immer mal vergessen.

Gruß Kimmi
Was muss ich den noch Transformieren? Wie mache ich das, habe dazu irgendwie nicht viel gefunden.
Aramis hat geschrieben:Prinzipiell sollte die Ausrichtung von 3DS-Modellen richtig sein, vorausgesetzt, die Modelle waren in der Quelldatei richtig herum :-)

Gibst du evtl das ConvertToLeftHanded-Flag an? Sollte prinzipiell fuer OpenGl nicht noetig sein.
Wenn ich die .3ds in Blender betrachte stimmt es. Das genannte ConvertToLeftHanded Flag ist nicht an wie du oben im code sehen kann :)

:?:

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 16.01.2012, 19:45
von Grinch
Nach deinem Code liest du zwar alle Meshes aus, aber nicht den Nodetree.
Die Nodes bilden den Modellbaum ab. Jeder Node hat eine Liste(1-n) von Meshes und eine Transformationsmatrix sowie 0-m Childnodes. Durch die Transformationsmatrix werden die Meshes richtig positioniert und du kannst ein Mesh auch an mehreren Stellen verwenden (z.B. ein Fenster an mehreren Stellen im Haus).
Die Transformationsmatrix für einen Node ist auch jeweils relativ zu seinem Parent. Dies muss beim Rendern durch Multiplikation der Matrizen beachtet werden.

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 16.01.2012, 20:59
von madmoses
Grinch hat geschrieben:Nach deinem Code liest du zwar alle Meshes aus, aber nicht den Nodetree.
Die Nodes bilden den Modellbaum ab. Jeder Node hat eine Liste(1-n) von Meshes und eine Transformationsmatrix sowie 0-m Childnodes. Durch die Transformationsmatrix werden die Meshes richtig positioniert und du kannst ein Mesh auch an mehreren Stellen verwenden (z.B. ein Fenster an mehreren Stellen im Haus).
Die Transformationsmatrix für einen Node ist auch jeweils relativ zu seinem Parent. Dies muss beim Rendern durch Multiplikation der Matrizen beachtet werden.
Wenn ich rausgefunden habe wie ich die Transformationsmatrix bekomme, muss ich dann (in meinen Fall OpenGL) mit glTranslatef( ); und glRotatef( ); in meinem code arbeiten?

ich mein wenn ich ein 3d objekt aus mehreren Meshes laden will, ist alles richtig an seiner position wo es sein soll und sieht auch so aus wie im assimp view. Der Spaß ist dann eben nur um 90grad gekippt. Und ich kippe
es jedes mal wenn ich es zeichne um 90grad zurück und das fast 1000mal pro Frame, das will ich verhindern in dem ich das Ganze direkt an in der richtigen form vorliegen habe.

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 16.01.2012, 21:30
von Schrompf
Wo bei 3D-Modellen oben ist, dazu existiert leider kein verpflichtender Standard. Einige Modelle musst Du drehen, andere nicht. Die Rechenzeit dafür kannst Du aber ignorieren... ein glRotate() verursacht nur eine Matrix-Multiplikation, davon kannst Du einige hundert Millionen pro Sekunde machen.

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 16.01.2012, 21:54
von madmoses
Schrompf hat geschrieben:Wo bei 3D-Modellen oben ist, dazu existiert leider kein verpflichtender Standard. Einige Modelle musst Du drehen, andere nicht. Die Rechenzeit dafür kannst Du aber ignorieren... ein glRotate() verursacht nur eine Matrix-Multiplikation, davon kannst Du einige hundert Millionen pro Sekunde machen.
Aber alle die ich bis jetzt runtergeladen sind auf der selben art und weiße falsch geneigt. In Blender aber immer richtig ausgerichtet. Da mache ich doch was falsch?


Ich berechne anhand der Mashes eine Bounding Box für meine Culling implementierung. Ich müsste dann halt per hand die Bounding Box auch ensprechend drehen, aber wollte das eigentlich verhindern und das kostet ja auch rechenzeit. Habe gehoft das ich das mit assimp machen lässt.

Momentan sieht meine zeichen Funktion so aus:

Code: Alles auswählen

void AllRoundObject::render(float x, float y, float z)
{
	if(sowi::Frustum::OUTSIDE == ((frustum->pointInFrustum(boundingBox.A.X + x,boundingBox.A.Y + y, boundingBox.A.Z + z)) |
								  (frustum->pointInFrustum(boundingBox.G.X + x,boundingBox.G.Y + y, boundingBox.G.Z + z))))
		outside++;
	else
	{
		inside++;
		glPushMatrix();
		glTranslatef(x, y, z);

	    glEnableClientState(GL_NORMAL_ARRAY);
	    glEnableClientState(GL_VERTEX_ARRAY);

	    glBindBuffer(GL_ARRAY_BUFFER, VBOnormalsID);
	    glNormalPointer(GL_FLOAT, 0, 0);

	    glBindBuffer(GL_ARRAY_BUFFER, VBOverticesID);
	    glVertexPointer(3, GL_FLOAT, 0, 0);

	    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOindicesID);
		glDrawElements(GL_TRIANGLES, this->numFaces*3, GL_UNSIGNED_INT, 0);

	    glDisableClientState(GL_VERTEX_ARRAY);
	    glDisableClientState(GL_NORMAL_ARRAY);
		glPopMatrix();
	}
}
Ich merke mir sozusagen jede transaltion, damit ich meine Boundinbox manuell verschiebe. Muss man das so machen oder kann ich das auch schöner machen? Mit schöner
meine ich das ich meine Boundingbox nicht manuell mit verschieben muss bei jeder Translation?

Vielen dank für eure schnellen antworten :)

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 17.01.2012, 12:16
von Grinch
Die Transformationsmatrix eines Nodes des Modells enthält alle 3 Faktoren, also Skalierung, Rotation und Translation. Du musst also quasi einen Matrixstack aufbauen, mit dem du das Modell zeichnest. Am Anfang steht die Identmatrix, also Nullpunkt ohne Veränderung. Diese wird dann mit der Transformationsmatrix des ersten Nodes multipliziert. Damit sind die Meshes dieses Knotens an der richtigen Stelle, rotiert und skaliert. Wenn der Node Childs hat, wird die jeweils aktuelle Worldmatrix genommen und mit der eigenen Transformationsmatrix multipliziert, wodurch sich der Child relativ zu seinem Parent verschiebt.
Es sieht dann also in etwa so aus:
Modell:

Code: Alles auswählen

Node
|-Childnode1
|    -ChildChildnode1
|-Childnode2
Matrizenmultiplikation:

Code: Alles auswählen

matN1*1
matC1*matN1*1
matCC1*matC1*matN1*1
matC2*matN1*1

1 ist die Identmatrix. Diese Multiplikation kann man aber auch wegoptimieren.
Ich kenne mich leider bei OpenGL nicht so aus, aber es wird hier auch sicher eine Funktion geben, in der man die Worldmatrix direkt setzen kann ohne glTranslatef oder glRotatef etc.

Re: Assimp .3ds modelle für OpenGL importieren

Verfasst: 18.01.2012, 15:42
von kimmi
Schau dir einfach mal das Beispiel assimp_simpleogl an, dort werden die Matrizen korrekt gesetzt. Das Beispiel findest du unter <assimp_root>/samples/simpleopengl .

Gruß Kimmi