Browse Source

Add ObjFile class to import 3d triangulated models from .obj files

Kolja Strohm 1 year ago
parent
commit
30ecb1e460
4 changed files with 183 additions and 0 deletions
  1. 2 0
      Framework.vcxproj
  2. 6 0
      Framework.vcxproj.filters
  3. 149 0
      ObjFile.cpp
  4. 26 0
      ObjFile.h

+ 2 - 0
Framework.vcxproj

@@ -246,6 +246,7 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClInclude Include="Maus.h" />
     <ClInclude Include="MausEreignis.h" />
     <ClInclude Include="Maybe.h" />
+    <ClInclude Include="ObjFile.h" />
     <ClInclude Include="RCPointer.h" />
     <ClInclude Include="ReferenceCounter.h" />
     <ClInclude Include="Slider.h" />
@@ -339,6 +340,7 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClCompile Include="Model3D.cpp" />
     <ClCompile Include="Model3DCollection.h" />
     <ClCompile Include="Model3DList.cpp" />
+    <ClCompile Include="ObjFile.cpp" />
     <ClCompile Include="Random.cpp" />
     <ClCompile Include="Reader.cpp" />
     <ClCompile Include="ReferenceCounter.cpp" />

+ 6 - 0
Framework.vcxproj.filters

@@ -378,6 +378,9 @@
     <ClInclude Include="VecN.h">
       <Filter>Headerdateien\Framework\Grafik</Filter>
     </ClInclude>
+    <ClInclude Include="ObjFile.h">
+      <Filter>Headerdateien\Framework\OS\Datei</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Maus.cpp">
@@ -611,6 +614,9 @@
     <ClCompile Include="Reader.cpp">
       <Filter>Quelldateien\Framework\IO</Filter>
     </ClCompile>
+    <ClCompile Include="ObjFile.cpp">
+      <Filter>Quelldateien\Framework\OS\Datei</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <FxCompile Include="DX12VertexShader.hlsl">

+ 149 - 0
ObjFile.cpp

@@ -0,0 +1,149 @@
+#include "ObjFile.h"
+#include "Vec2.h"
+#include "Model3D.h"
+
+using namespace Framework;
+
+
+ObjFile::ObjFile(const char* path)
+	: ReferenceCounter()
+{
+	file.setDatei(path);
+	file.open(Datei::Style::lesen);
+	Text* line = file.leseZeile();
+	while (line)
+	{
+		if (line->positionVon("o ") == 0)
+			objectNames.add(line->getTeilText(2));
+		line->release();
+		line = file.leseZeile();
+	}
+	file.close();
+}
+
+Vec3<int> ObjFile::parseIndex(Text* s)
+{
+	Text* x = s->getTeilText(0, s->positionVon("/"));
+	Text* y = s->getTeilText(s->positionVon("/") + 1, s->positionVon("/", 1));
+	Text* z = s->getTeilText(s->positionVon("/", 1) + 1);
+	Vec3<int> result((int)*x, (int)*y, (int)*z);
+	x->release();
+	y->release();
+	z->release();
+	s->release();
+	return result;
+}
+
+void ObjFile::readModel(Model3DData* zTarget)
+{
+	Array<Vec3<float>> vertices;
+	Array<Vec2<float>> textureCoordinates;
+	Array<Vec3<float>> normals;
+	Array<Vec3<int>> indices;
+	// read model info
+	Text* line = file.leseZeile();
+	while (line)
+	{
+		if (line->positionVon("o "))
+		{
+			line->release();
+			break;;
+		}
+		if (line->positionVon("v ") == 0)
+		{
+			Text* x = line->getTeilText(2, line->positionVon(" ", 1));
+			Text* y = line->getTeilText(line->positionVon(" ", 1) + 1, line->positionVon(" ", 2));
+			Text* z = line->getTeilText(line->positionVon(" ", 2) + 1);
+			vertices.add(Vec3<float>((float)*x, (float)*y, (float)*z));
+			x->release();
+			y->release();
+			z->release();
+		}
+		if (line->positionVon("vt ") == 0)
+		{
+			Text* x = line->getTeilText(3, line->positionVon(" ", 1));
+			Text* y = line->getTeilText(line->positionVon(" ", 1) + 1);
+			textureCoordinates.add(Vec2<float>((float)*x, (float)*y));
+			x->release();
+			y->release();
+		}
+		if (line->positionVon("vn ") == 0)
+		{
+			Text* x = line->getTeilText(3, line->positionVon(" ", 1));
+			Text* y = line->getTeilText(line->positionVon(" ", 1) + 1, line->positionVon(" ", 2));
+			Text* z = line->getTeilText(line->positionVon(" ", 2) + 1);
+			normals.add(Vec3<float>((float)*x, (float)*y, (float)*z));
+			x->release();
+			y->release();
+			z->release();
+		}
+		if (line->positionVon("f ") == 0)
+		{
+			// only triangulated meshes ares supported
+			Text* p1 = line->getTeilText(3, line->positionVon(" ", 1));
+			Text* p2 = line->getTeilText(line->positionVon(" ", 1) + 1, line->positionVon(" ", 2));
+			Text* p3 = line->getTeilText(line->positionVon(" ", 2) + 1);
+			indices.add(parseIndex(p1));
+			indices.add(parseIndex(p2));
+			indices.add(parseIndex(p3));
+		}
+		line->release();
+		line = file.leseZeile();
+	}
+	// compute vertex data and index buffer
+	Array<Vertex3D> modelData;
+	int* indexList = new int[indices.getEintragAnzahl()];
+	int rInd = 0;
+	for (Vec3<int> index : indices)
+	{
+		Vertex3D current;
+		current.pos = vertices.get(index.x - 1);
+		current.tPos = textureCoordinates.get(index.y - 1);
+		current.normal = normals.get(index.z - 1);
+		current.knochenId = 0;
+		int ind = 0;
+		for (Vertex3D& other : modelData)
+		{
+			if (other.pos == current.pos && other.tPos == current.tPos && other.normal == current.normal)
+				break;
+			ind++;
+		}
+		if (modelData.getEintragAnzahl() == ind)
+			modelData.add(current);
+		indexList[rInd++] = ind;
+	}
+	Vertex3D* vertexData = new Vertex3D[modelData.getEintragAnzahl()];
+	int ind = 0;
+	for (Vertex3D& vertex : modelData)
+		vertexData[ind++] = vertex;
+	zTarget->setVertecies(vertexData, modelData.getEintragAnzahl());
+	Polygon3D* polygon = new Polygon3D();
+	polygon->indexAnz = indices.getEintragAnzahl();
+	polygon->indexList = indexList;
+	zTarget->addPolygon(polygon);
+}
+
+bool ObjFile::loadModel(const char* name, Model3DData* zTarget)
+{
+	file.open(Datei::Style::lesen);
+	Text* line = file.leseZeile();
+	while (line)
+	{
+		if (line->positionVon("o ") == 0 && line->positionVon(name) == 2 && line->getLength() == textLength(name) + 2)
+		{
+			readModel(zTarget);
+			line->release();
+			file.close();
+			return 1;
+		}
+		line->release();
+		line = file.leseZeile();
+	}
+	file.close();
+	return 0;
+}
+
+const RCArray<Text>& ObjFile::getContainedModelNames() const
+{
+	return objectNames;
+}

+ 26 - 0
ObjFile.h

@@ -0,0 +1,26 @@
+#pragma once
+
+#include "ReferenceCounter.h"
+#include "Array.h"
+#include "Datei.h"
+#include "Vec3.h"
+
+namespace Framework
+{
+	class Model3DData;
+
+	class ObjFile : public ReferenceCounter
+	{
+	private:
+		Datei file;
+		RCArray<Text> objectNames;
+
+		Vec3<int> parseIndex(Text* s);
+		void readModel(Model3DData* zTarget);
+
+	public:
+		DLLEXPORT ObjFile(const char* path);
+		DLLEXPORT bool loadModel(const char* name, Model3DData* zTarget);
+		DLLEXPORT const RCArray<Text>& getContainedModelNames() const;
+	};
+}