[Directx] Eigenes 3D Format



  • Hi schonmal einen riesen dank hab mir jetzt die msdn seite durchgelesen und ein wenig gegoogelt bin mir aber garnicht sicher ob ich auf dem Richtigen Weg bin.

    Also ich habe folgenden Code geschrieben:

    Ich habe eine Klasse Objects die Listen von Objekten verwaltet.

    void Objects::AddTriangel(unsigned int x, unsigned int y, unsigned int Width, unsigned int Height) {
    		LPDIRECT3DINDEXBUFFER9 m_ib;
    		MyDirectx->Device->CreateIndexBuffer(4 * sizeof(Vertex), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_ib, NULL);
    		WORD *indices = NULL;
    		m_ib->Lock( 0, 0, (void**)&indices, 0 );
    		indices[0]=0;
    		indices[1]=1;
    		indices[2]=3;
    		m_ib->Unlock();
    		Vertex tmp[] =
    		{
    			{ x, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },
    			{ x + Width, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },
    			{ x - Width, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
    		};
    		MapObjects.push_back(Object(tmp, sizeof(tmp), 3, 1, m_ib));
    	}
    

    Ich lege dann woanders ein Dreieck an:

    Objects.AddTriangel(320, 50, 200, 350);
    

    So die klasse Object reicht immoment nur durch (Das wird sich ändern..)

    Object::Object(struct Vertex *Vertices, unsigned int Size, unsigned int NumVertices, unsigned int Triangles, LPDIRECT3DINDEXBUFFER9 Indices) : Mesh(Vertices, Size, NumVertices, Triangles, Indices) {
    	}
    

    So die klasse Mesh hat jetzt 2 Wichtige funktionen einmal den Konstruktor und dann die Funktion zum Rendern:

    Mesh::Mesh(struct Vertex *Vertices, unsigned int Size, unsigned int NumVertices, unsigned int Triangles, LPDIRECT3DINDEXBUFFER9 Indices) {
    		Buffer = NULL;
    		MyDirectx->Device->CreateVertexBuffer(3 * sizeof(Vertex), 0, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &Buffer, NULL);
    		void *pVoid;
    		Buffer->Lock(0, 0, (void**)&pVoid, 0);
    		memcpy(pVoid, Vertices, Size);
    		Buffer->Unlock();
    		this->NumVertices = NumVertices;
    		this->Triangles = Triangles;
    		this->Indices = Indices;
    	}
    	void Mesh::Render3DSolid() {
    		MyDirectx->Device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
    		MyDirectx->Device->SetStreamSource(0, Buffer, 0, sizeof(Vertex));
    		MyDirectx->Device->SetIndices(Indices);
    		//MyDirectx->Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
    		MyDirectx->Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, Triangles);  
    	}
    

    Wenn ich das so wie es immoment ist Starte seh ich leider garnichts... Wenn ich die immoment auskommentierte funktion ohne Indices nutze dann wird das Dreieck gezeichnet aber ich möchte ja nun zur Variante mit Indices kommen. Was mache ich falsch?



  • Du legst jetzt fuer jede "Triangel" einen neuen Indexbuffer an.
    Die Grundidee eines Buffers liegt aber darin, mehr als ein Element zu beinhalten.

    CreateIndexBuffer(4 * sizeof(Vertex), ...

    Wieviele Indices passen da jetzt rein?

    CreateVertexBuffer(3 * sizeof(Vertex), ...

    Und wenn Du mal mehr als ein Dreieck hast?

    indices[0]=0;
    indices[1]=1;
    indices[2]=3;

    Vertex #2 interessiert Dich nich so?



  • hellihjb schrieb:

    Du legst jetzt fuer jede "Triangel" einen neuen Indexbuffer an.
    Die Grundidee eines Buffers liegt aber darin, mehr als ein Element zu beinhalten.

    Ja das ist mir schon klar aber das dient ja grade alles übungszwecken. Ich komme halt mehr aus dem Linux und OpenGL bereich => taste mich grade Stückchen für Stückchen mit eurer Hilfe vorran.

    hellihjb schrieb:

    CreateIndexBuffer(4 * sizeof(Vertex), ...

    Wieviele Indices passen da jetzt rein?

    Viermal die größe meiner Vertex struktur wieso? Drei reichen auch oder was willst du mir sagen?

    hellihjb schrieb:

    CreateVertexBuffer(3 * sizeof(Vertex), ...

    Und wenn Du mal mehr als ein Dreieck hast?

    Dann lege ich 2 VertexBuffer an? Oder sollte man das nicht?

    hellihjb schrieb:

    indices[0]=0;
    indices[1]=1;
    indices[2]=3;

    Vertex #2 interessiert Dich nich so?

    [/quote]

    Danke wo war ich da gestern nur mit meinen gedanken. Das klappt jetzt.

    Jetzt hab ich mal gleich den Code für ein Viereck geschrieben:

    void Objects::AddQuad(unsigned int x, unsigned int y, unsigned int Width, unsigned int Height) {
    		LPDIRECT3DINDEXBUFFER9 m_ib;
    		MyDirectx->Device->CreateIndexBuffer(8 * sizeof(Vertex), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_ib, NULL);
    		WORD *indices = NULL;
    		m_ib->Lock( 0, 0, (void**)&indices, 0 );
    		indices[0] = 0;
    		indices[1] = 1;
    		indices[2] = 3;
    		indices[3] = 3;
    		indices[4] = 1;
    		indices[5] = 2;
    		m_ib->Unlock();
    		Vertex tmp[] =
    		{
    			{ x, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },
    			{ x + Width, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },
    			{ x, y - Height, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
    			{ x + Width, y - Height, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
    		};
    		MapObjects.push_back(Object(tmp, sizeof(tmp), 4, 2, m_ib));
    	}
    

    Dabei entsteht dann malwieder garnichts...

    mfg nils



  • Wieviele Indices passen da jetzt rein?

    Viermal die größe meiner Vertex struktur wieso?

    Du willst aber keine Vertices im Indexbuffer speichern 🙂
    Ausserdem willst Du fuer jedes Objekt *einen* Vertex- und *einen* Indexbuffer anlegen um die Grafikkarte mit moeglichst geringem Aufwand moeglichst lange zu beschaeftigen.
    Die GPU ist eine Streamarchitektur und Bufferwechsel entsprechend teuer. Jedes Polygon in einem eigenen Buffer zu halten ist nicht umsetzbar.



  • Sry doppelpost is keine absicht



  • Kann ich denn Sachen zu aus einem Buffer wieder in ein Array zurück wandeln? Bzw kann ich die einzelenen sachen aus dem Buffer verändern? z.b. für Bewegung?



  • Du kannst den Buffer locken und mit neuen Daten ueberschreiben oder die dafuer notwendigen Berechnungen im Vertex-Shader ausfuehren.
    Aus einem Vertexbuffer zu lesen kann um ein Vielfaches langsamer sein.



  • Naja es geht grad nur um den Editor den ich mir zurechtschreibe um das ganze ein Wenig zu testen.
    Ich wöde den Buffer dann immer wenn was hinzugefügt wird größer machen wollen und müsste dazu die alten Daten erstmal in den Neuen kopiern geht sowas? (Performant muss das an der stelle nicht sein).

    Bei Bewegungen wödest du dann den ganzen Buffer neu schreiben oder kann man nur bestimmte stellen des Buffers überschreiben?

    mfg nils


  • Mod

    bei einem editor waere es nicht schlimm wenn du die daten auch local im speicher haettest, du kommst frueher oder spaeter auf die idee damit noch was anderes anzustellen (z.b. picking) und dann musst du oefter drauf zugreifen, was nicht smart waere bei nem vertexbuffer von d3d 😉

    zudem, wenn es nur ein 'editor' ist, kannst du dir eventuell immer noch ein wenig 'puffer' hintern dran allokieren, sodass, falls noch ein paar mehr vertices dazu kommen, du keinen neuen buffer allokieren musst. ab und zu musst du das dann vielleicht wieder, aber das sollte bei einem editor absolut kein performance problem darstellen. (niemand wird sich beschweren wenn es einen ruckler geben sollte 😉 )



  • rapso schrieb:

    (niemand wird sich beschweren wenn es einen ruckler geben sollte 😉 )

    Stimm da das wie gesagt alles dem Spaß dient werde wahrscheinlich nur ich das ganze einsetzen und das auch nur zum testen 😃

    Ich finde grade keine Funktion um die Vertex und Index Buffer wieder zu "löschen", gibt es da keine Funktion? Und ich erstell den neuen einfach "Über" dem alten?

    mfg nils


  • Mod

    ->Release(), wie bei allen resourcen.
    und nein, du erstellst keinen drueber, danaben oder daruntern, du hast nur CreateVertexbuffer und der treiber sucht sich aus ws er damit macht.



  • Jau danke dann werd ich da heut Abend mal weiter dran rumspielen muss ja jetzt doch nen bisschen was umnstellen. Melde mich wieder wenns noch Probleme/Fragen gibt.

    Erstmal ein riesen danke an die wunderbare hilfe die ihr mir gegeben habt.

    mfg nils 🙂



  • Es hat sich da jetzt doch gleich eine neue Frage aufgedrängt. Und zwar immoment haben meine Gegenstände ja alle nur Farben wie mach ich das denn dann das die verschiedene Texturen haben können?

    Bekommt die Vertex Struktur dann anstatt D3DCOLOR_XRGB ein enstprechendes Textur Objekt?

    Und es ist dann auch richtig das ich den Buffer jedesmal neu erstellen muss wenn sich ein Objekt bewegt oder?

    mfg nils



  • Bekommt die Vertex Struktur dann ein Textur Objekt?

    Das wuerde keinen Sinn machen weil ja sonst fuer die jeweiligen Eckpunkte eines Polygons unterschiedliche Texturen definiert sein koennten.
    Stattdessen weisst man jedem Polygon eine Material-ID (das Material beinhaltet neben anderen Parametern auch die Textur(en)).
    Um nicht jedes Polygon einzelnd zeichnen und staendig Renderstates aendern zu muessen kannst Du fuer das Mesh zb eine Liste von verwendeten Materialien halten und fuer jedes Material eine Liste von Polygonen (oder dessen Indices) die es verwenden.



  • Hmm aber wie funktioniert das Rendern denn dann?
    Mal angenommen ich möchte für meinen Test Editor erstmal nur die ansicht mit Farben und dann irgendwann eine mit Texturen dann soll man da aber trozdem noch umschalten können.

    Ist sowas möglich wie teile ich Direct x dann mit wie er rendern soll?

    mfg nils



  • Definiere bitte etwas genauer was "die ansicht mit Farben" und "eine mit Texturen" darstellen sollen und in wie fern sich diese unterscheiden.
    Daraus muesste sich auch schon ergeben was Du unternehmen musst um zwischen beiden umzuschalten.
    Allgemein koenntest Du zb ein "internes" Material definieren, dass im Falle einer gewaehlten Darstellungsoption das Rendering uebernimmt.
    Du solltest Dir auch mal die Beispiele vom DirectX-SDK angucken.



  • hellihjb schrieb:

    Definiere bitte etwas genauer was "die ansicht mit Farben" und "eine mit Texturen" darstellen sollen und in wie fern sich diese unterscheiden.
    Daraus muesste sich auch schon ergeben was Du unternehmen musst um zwischen beiden umzuschalten.
    Allgemein koenntest Du zb ein "internes" Material definieren, dass im Falle einer gewaehlten Darstellungsoption das Rendering uebernimmt.
    Du solltest Dir auch mal die Beispiele vom DirectX-SDK angucken.

    Lassen wir das mal vorerst. Habe jetzt mal nen großen Teil neugeschrieben.

    Die Mesh klasse ist rausgeflogen.
    Die Objects Klasse:

    Objects::Objects() : ClassVertexBuffer(&MapObjects), ClassIndexBuffer(&MapObjects) {
    		AddTriangle(120.0, 400.0, 200.0, 350.0);
    		//AddQuad(120.0, 400.0, 200.0, 350.0);
    	}
    
    	void Objects::AddTriangle(float x, float y, float Width, float Height) {
    		list<Vertex> Vertices;
    		Vertices.push_back(Vertex(x, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)));
    		Vertices.push_back(Vertex(x + Width, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0)));
    		Vertices.push_back(Vertex(x - Width, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0)));
    
    		list<WORD> Indices;
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 0);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 1);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 2);
    
    		MapObjects.push_back(Object(Vertices, sizeof(Vertices), Indices, 3, 3, 1));
    		ClassVertexBuffer.GenerateNew();
    		ClassIndexBuffer.GenerateNew();
    	}
    
    	void Objects::Render3D(const RenderType RenderType) {
    		MyDirectx->Device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
    		cout<<"Get Buffer Pointer: "<<ClassVertexBuffer.GetBuffer()<<endl;
    		if(FAILED(MyDirectx->Device->SetStreamSource(0, ClassVertexBuffer.GetBuffer(), 0, sizeof(Vertex)))) {
    			cout<<"Error"<<endl;
    		}
    		if(FAILED(MyDirectx->Device->SetIndices(ClassIndexBuffer.GetBuffer()))) {
    			cout<<"Error"<<endl;
    		}
    		if(FAILED(MyDirectx->Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, ClassVertexBuffer.GetNumVertices(), 0, ClassVertexBuffer.GetNumTriangles()))) {
    			cout<<"Error"<<endl;
    		}
    		cout<<ClassVertexBuffer.GetNumVertices()<<" "<<ClassVertexBuffer.GetNumTriangles()<<endl;
    		MyDirectx->DrawText("Finished Rendering", 20, 420);
    	}
    

    Die Object Klasse Merkt sich dann alles für ein Object (Nur Der header):

    class Object {
    		private:
    			unsigned int VerticesSize, NumVertices, NumIndices, NumTriangles;
    			std::list<Vertex> Vertices;
    			std::list<WORD> Indices;
    		protected:
    		public:
    			/* Methods */
    			Object(std::list<Vertex> Vertices, unsigned int VerticesSize, std::list<WORD> Indices, unsigned int NumIndices, unsigned int NumVertices, unsigned int NumTriangles);
    			unsigned int GetVerticesSize();
    			unsigned int GetNumVertices();
    			unsigned int GetNumIndices();
    			unsigned int GetNumTriangles();
    			std::list<Vertex> GetVertices();
    			std::list<WORD> GetIndices();
    	};
    

    So dann hab ich eine Klasse IndexBuffer:

    IndexBuffer::IndexBuffer(std::list<Object> *ObjectList) {
    		Init = false;
    		this->ObjectList = ObjectList;
    		GenerateNew();
    		Init = true;
    	}
    	unsigned int IndexBuffer::GetNumIndices() {
    		unsigned int NumIndices = 0;
    		for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    			NumIndices += it->GetNumIndices();
    		}
    		return NumIndices;
    	}
    
    	void IndexBuffer::GenerateNew() {
    		Clear();
    		unsigned int NumIndices = GetNumIndices();
    		MyDirectx->Device->CreateIndexBuffer(NumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &Buffer, NULL);
    		WORD *Indices = NULL;
    		if(NumIndices > 0) {
    			Buffer->Lock( 0, 0, (void**)&Indices, 0 );
    			unsigned int i = 0;
    			for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    				list<WORD> IndicesList = it->GetIndices();
    				for(list<WORD>::iterator it = IndicesList.begin(); it != IndicesList.end(); it++) {
    					Indices[i] = (*it);
    					i++;
    				}
    			}
    			Buffer->Unlock();
    			cout<<"List Größe: "<<NumIndices<<endl;
    			for(unsigned int i = 0; i < 3; i++) {
    				cout<<"Indices "<<i<<" : "<<Indices[i]<<endl;
    			}
    		}else{
    			cout<<"No Indices"<<endl;
    		}
    	}
    	void IndexBuffer::Clear() {
    		if(Init) {
    			//Buffer->Release(); <--- Da segfault es wohl iwie deswegen auskommentiert
    		}
    	}
    

    Und noch eine für Vertexe:

    VertexBuffer::VertexBuffer(std::list<Object> *ObjectList) {
    		Init = false;
    		this->ObjectList = ObjectList;
    		GenerateNew();
    		Init = true;
    	}
    
    	unsigned int VertexBuffer::GetNumTriangles() {
    		unsigned int NumTriangles = 0;
    		for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    			NumTriangles += it->GetNumTriangles();
    		}
    		return NumTriangles;
    	}
    
    	unsigned int VertexBuffer::GetNumVertices() {
    		unsigned int NumVertices = 0;
    		for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    			NumVertices += it->GetNumVertices();
    		}
    		return NumVertices;
    	}
    
    	unsigned int VertexBuffer::GetVerticesSize() {
    		unsigned int VerticesSize = 0;
    		if(!ObjectList->empty()) {
    			for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    				VerticesSize += it->GetVerticesSize();
    			}
    		}
    		return VerticesSize;
    	}
    	void VertexBuffer::GenerateNew() {
    		Clear();
    		unsigned int VerticesSize = GetVerticesSize(), NumVertices = GetNumVertices();
    		Vertex *Vertices = new Vertex[NumVertices];
    		unsigned int i = 0;
    		for(list<Object>::iterator it = ObjectList->begin(); it != ObjectList->end(); it++) {
    			list<Vertex> VerticesList = it->GetVertices();
    			for(list<Vertex>::iterator it = VerticesList.begin(); it != VerticesList.end(); it++) {
    				Vertices[i] = (*it);
    				i++;
    			}
    		}
    		MyDirectx->Device->CreateVertexBuffer(VerticesSize * sizeof(Vertex), 0, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &Buffer, NULL);
    		if(NumVertices > 0) {
    			void *pVoid;
    			Buffer->Lock(0, 0, (void**)&pVoid, 0);
    			memcpy(pVoid, Vertices, VerticesSize);
    			Buffer->Unlock();
    			cout<<"List Size: "<<VerticesSize<<endl;
    			for(unsigned int i = 0; i < 3; i++) {
    				cout<<"Vertexe "<<i<<" : x: "<<Vertices[i].x<<" y: "<<Vertices[i].y<<endl;
    			}
    		}
    		delete [] Vertices;
    		cout<<"Buffer pointer: "<<Buffer<<endl;
    	}
    	void VertexBuffer::Clear() {
    		if(Init) {
    			//Buffer->Release(); <-- Ebenfalls Segfault
    		}
    	}
    

    Achja und Vertex:

    class Vertex {
    	public:
    		int a;
    		float x, y, z, rwh;
    		DWORD Color;
    		inline Vertex(float x, float y, float z, float rwh, DWORD Color) {
    			this->x = x;
    			this->y = y;
    			this->z = z;
    			this->rwh = rwh;
    			this->Color = Color;
    		}
    
    		inline Vertex() {
    			this->x = 0;
    			this->y = 0;
    			this->z = 0;
    			this->rwh = 0;
    			this->Color = 0;
    		}
    	};
    

    Leider wird mir so Rein garnichts angezeigt (also kein Dreieck das Finished Rendering schon) es wird nirgends error Ausgegben und die Debug ausgeben (sie screenshot) sehen auch gut aus.
    Und wieso segfaulten die Release() ?

    http://www.imgwelt.de/show.php?code=AI2147L9Y2W

    mfg nils



  • Was soll das "int a" in "Vertex" ?



  • Ok danke das ist von einem Test über geblieben behebt aber leider nicht das Problem.



  • Jetzt wirds ganz komisch wenn ich noch folgendes mache:

    Und ein Quad genau über dem Dreieck erstelle sehe ich das Dreieck?!

    Objects::Objects() : ClassVertexBuffer(&MapObjects), ClassIndexBuffer(&MapObjects) {
    		AddTriangle(120.0, 400.0, 200.0, 350.0);
    		AddQuad(120.0, 400.0, 200.0, 350.0);
    	}
    
    void Objects::AddQuad(float x, float y, float Width, float Height) {
    		list<Vertex> Vertices;
    		Vertices.push_back(Vertex(x, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)));
    		Vertices.push_back(Vertex(x + Width, y, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)));
    		Vertices.push_back(Vertex(x, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)));
    		Vertices.push_back(Vertex(x + Width, y + Height, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)));
    
    		list<WORD> Indices;
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 0);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 3);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 2);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 0);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 1);
    		Indices.push_back(ClassIndexBuffer.GetNumIndices() + 3);
    
    		MapObjects.push_back(Object(Vertices, sizeof(Vertices), Indices, 6, 4, 2));
    		ClassVertexBuffer.GenerateNew();
    		ClassIndexBuffer.GenerateNew();
    
    	}
    

    Irgend was ist da noch nicht so richtig...


Anmelden zum Antworten