diff --git a/TheRepo/DoWhateverYouWant/DoWhateverYouWant.csproj b/TheRepo/DoWhateverYouWant/DoWhateverYouWant.csproj
index b218602..6b70cc0 100644
--- a/TheRepo/DoWhateverYouWant/DoWhateverYouWant.csproj
+++ b/TheRepo/DoWhateverYouWant/DoWhateverYouWant.csproj
@@ -8,6 +8,7 @@
+
diff --git a/TheRepo/TheLabs/ModelLoader.cs b/TheRepo/TheLabs/ModelLoader.cs
new file mode 100644
index 0000000..9e1faab
--- /dev/null
+++ b/TheRepo/TheLabs/ModelLoader.cs
@@ -0,0 +1,77 @@
+namespace TheLabs;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Assimp; // The library we just installed
+using OpenTK.Mathematics;
+
+public static class ModelLoader
+{
+ public static Mesh LoadMesh(string path)
+ {
+ var importer = new AssimpContext();
+
+ var scene = importer.ImportFile(path, PostProcessSteps.Triangulate | PostProcessSteps.JoinIdenticalVertices);
+
+ if (scene == null || scene.SceneFlags.HasFlag(SceneFlags.Incomplete) || scene.RootNode == null)
+ {
+ throw new Exception("Error loading model: " + path);
+ }
+
+ // --- NEW LOGIC: Combine all meshes into one ---
+ List allVertices = new List();
+ List allIndices = new List();
+
+ // We need to track how many vertices we've added so far
+ // so the indices point to the correct new location
+ uint indexOffset = 0;
+
+ // Loop through EVERY mesh found in the file (Legs, Torso, Head, etc.)
+ foreach (var mesh in scene.Meshes)
+ {
+ // 1. Process Vertices for this specific part
+ for (int i = 0; i < mesh.VertexCount; i++)
+ {
+ // Position (x, y, z)
+ var pos = mesh.Vertices[i];
+ allVertices.Add(pos.X);
+ allVertices.Add(pos.Y);
+ allVertices.Add(pos.Z);
+
+ // Texture Coordinates (u, v)
+ if (mesh.HasTextureCoords(0))
+ {
+ var uv = mesh.TextureCoordinateChannels[0][i];
+ allVertices.Add(uv.X);
+ allVertices.Add(uv.Y);
+ }
+ else
+ {
+ allVertices.Add(0.0f);
+ allVertices.Add(0.0f);
+ }
+ }
+
+ // 2. Process Indices for this specific part
+ for (int i = 0; i < mesh.FaceCount; i++)
+ {
+ var face = mesh.Faces[i];
+ for (int j = 0; j < face.IndexCount; j++)
+ {
+ // CRITICAL: We add the offset to the index!
+ // If the leg had 100 vertices, the first vertex of the torso
+ // needs to be index 100, not 0.
+ allIndices.Add((uint)(face.Indices[j] + indexOffset));
+ }
+ }
+
+ // Increase the offset by the number of vertices we just added
+ indexOffset += (uint)mesh.VertexCount;
+ }
+
+ // Return one giant Mesh containing the whole character
+ return new Mesh(allVertices.ToArray(), allIndices.ToArray(), Mesh.VertexLayout.PosTex);
+ }
+
+
+}
\ No newline at end of file
diff --git a/TheRepo/TheLabs/MyExampleWindow.cs b/TheRepo/TheLabs/MyExampleWindow.cs
index ff4a03d..a81e44a 100644
--- a/TheRepo/TheLabs/MyExampleWindow.cs
+++ b/TheRepo/TheLabs/MyExampleWindow.cs
@@ -1,4 +1,5 @@
-using OpenTK.Graphics.OpenGL4;
+using Assimp;
+using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Windowing.Desktop;
@@ -15,23 +16,21 @@ namespace TheLabs
// Negative X coordinates move to the left, positive X move to the right.
// Negative Y coordinates move to the bottom, positive Y move to the top.
// OpenGL only supports rendering in 3D, so to create a flat triangle, the Z coordinate will be kept as 0.
-
+
+ private SceneNode _rootNode;
+ private SceneNode _characterNode;
+ private SceneNode _buildingNode;
private Shader _shader;
private Camera _camera;
// - Resources that only need to be created once
- private Mesh _cubeMesh;
- private Mesh _circleMesh;
- private Mesh _cylinderMesh;
- private Texture _cubeTexture;
- private Texture _cubeTexture2;
- private float _rotation;
+ private Mesh _exampleObject;
+ private Mesh _buildingObject;
+ private Texture _texture;
+ private RenderObject _render;
+ private RenderObject _buildingRender;
+ float _rotation = 0.0f;
// -- Scene Objects
- private RenderObject _cubeObject;
- private RenderObject _cubeObject2;
- private RenderObject _circleObject;
- private RenderObject _cylinderObject;
- private Bus _bus;
private Vector3 _cameraPosition = new Vector3(0.0f, 0.0f, -3.0f);
private Vector3 _cameraFront = new Vector3(0.0f, 0.0f, -1.0f);
@@ -62,21 +61,32 @@ namespace TheLabs
//GL.Disable(EnableCap.CullFace);
//GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
- // Set The background color to a nice blue.
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
GL.Enable(EnableCap.DepthTest);
_camera = new Camera(_cameraPosition, _cameraFront, _cameraUp);
+ _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
+ _texture = new Texture("Textures/texture-a.png");
+
+ _rootNode = new SceneNode();
+ _exampleObject = ModelLoader.LoadMesh("Objects/cat.obj");
+ _buildingObject = ModelLoader.LoadMesh("Objects/building1.obj");
+ _render = new RenderObject(_exampleObject, _shader, _texture);
+ _buildingRender = new RenderObject(_buildingObject, _shader, _texture);
+
+ _characterNode = new SceneNode(_render);
+ _characterNode.Position = new Vector3(0.0f, -1.0f, 0.0f);
+ _rootNode.AddChild(_characterNode);
+
+ _buildingNode = new SceneNode(_buildingRender);
+ _buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f);
+ _rootNode.AddChild(_buildingNode);
+
+
+
CursorState = CursorState.Grabbed;
-
- _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
- _cubeTexture = new Texture("Textures/placeholder.png");
- _cubeTexture2 = new Texture("Textures/placeholder.png");
-
- _bus = new Bus(_cubeTexture, _shader);
-
-
-
+
+
}
@@ -105,9 +115,8 @@ namespace TheLabs
0.1f,
100.0f
);
-
// --- Draw Scene Objects ---
- _bus.DrawBus(view, projection);
+ _rootNode.Draw(view, projection, Matrix4.Identity);
SwapBuffers();
}
diff --git a/TheRepo/TheLabs/RenderObject.cs b/TheRepo/TheLabs/RenderObject.cs
index 21ae1fc..05fa7fb 100644
--- a/TheRepo/TheLabs/RenderObject.cs
+++ b/TheRepo/TheLabs/RenderObject.cs
@@ -28,7 +28,7 @@ public class RenderObject
Shader.Use();
Shader.SetInt("uTexture", 0);
// 2. Bind Texture
- Texture.Use(); // Assumes you have a Texture class
+ Texture.Use();
// 3. Calculate Model Matrix
Matrix4 model = Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Position);
int modelLoc = GL.GetUniformLocation(Shader.Handle, "model");
diff --git a/TheRepo/TheLabs/SceneNode.cs b/TheRepo/TheLabs/SceneNode.cs
new file mode 100644
index 0000000..3de370f
--- /dev/null
+++ b/TheRepo/TheLabs/SceneNode.cs
@@ -0,0 +1,45 @@
+using OpenTK.Mathematics;
+using System.Collections.Generic;
+
+namespace TheLabs;
+
+public class SceneNode
+{
+ public RenderObject? RenderObject;
+
+ public List Children = new List();
+
+ public Vector3 Position = Vector3.Zero;
+ public Quaternion Rotation = Quaternion.Identity;
+ public Vector3 Scale = Vector3.One;
+
+ public SceneNode(RenderObject? renderObject = null)
+ {
+ RenderObject = renderObject;
+ }
+
+ public void AddChild(SceneNode child)
+ {
+ Children.Add(child);
+ }
+
+ public void Draw(Matrix4 view, Matrix4 projection, Matrix4 parentTransform)
+ {
+ Matrix4 localTransform = Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Position);
+ Matrix4 globalTransform = localTransform * parentTransform;
+
+ if (RenderObject != null)
+ {
+ RenderObject.Position = Vector3.Zero;
+ RenderObject.Rotation = Quaternion.Identity;
+ RenderObject.Scale = Vector3.One;
+
+ RenderObject.Draw(view, projection);
+ }
+
+ foreach (var child in Children)
+ {
+ child.Draw(view, projection, globalTransform);
+ }
+ }
+}
\ No newline at end of file
diff --git a/TheRepo/TheLabs/Shapes/Bus.cs b/TheRepo/TheLabs/Shapes/Bus.cs
index 9cc40f5..1e35e71 100644
--- a/TheRepo/TheLabs/Shapes/Bus.cs
+++ b/TheRepo/TheLabs/Shapes/Bus.cs
@@ -5,85 +5,70 @@ namespace TheLabs.Shapes;
public class Bus
{
+ public SceneNode MainNode;
+
private Mesh _wheelMesh;
- private RenderObject _wheelObject;
+ private Mesh _bodyMesh;
+ private Mesh _roofMesh;
- private Texture _wheelTexture;
- private Shader _wheelShader;
- private Texture _bodyTexture;
- public Bus(Texture texture, Shader shader)
+ public Bus(Texture wheelTexture,Texture bodyTexture, Shader shader)
{
- _wheelTexture = new Texture("Textures/rubber.jpg");
- _wheelShader = shader;
-
- _bodyTexture = new Texture("Textures/rust.png");
- }
-
- public void DrawWheel(Matrix4 view, Matrix4 projection, Vector3 position)
- {
- Matrix4 localTransform = Matrix4.Identity;
- //Matrix4 comboTransform = localTransform * _wheelObject.Transform;
-
_wheelMesh = ShapeFactory.CreateTexturedCylinder();
- _wheelObject = new RenderObject(_wheelMesh, _wheelShader, _wheelTexture);
+ _bodyMesh = ShapeFactory.CreateTexturedCube();
+ _roofMesh = ShapeFactory.CreateTexturedCylinder();
- // Front Left Wheel
- _wheelObject.Position = new Vector3(position);
- _wheelObject.Scale = new Vector3(0.3f, 0.1f, 0.2f);
- _wheelObject.Rotation = Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(90.0f));
+ MainNode = new SceneNode();
- _wheelObject.Draw(view, projection);
+ // Building the body
+ var bodyObj = new RenderObject(_bodyMesh, shader, bodyTexture);
+ var bodyNode = new SceneNode(bodyObj);
+ bodyNode.Scale = new Vector3(1.5f, 0.5f, 0.5f);
+ bodyNode.Scale = new Vector3(0.0f, 0.0f, 0.0f);
+ MainNode.AddChild(bodyNode);
- }
-
- public void drawBody(Matrix4 view, Matrix4 projection)
- {
- Mesh bodyMesh = ShapeFactory.CreateTexturedCube();
- RenderObject bodyObject = new RenderObject(bodyMesh, _wheelShader, _bodyTexture);
+ // Building the body
+ var roofObj = new RenderObject(_roofMesh, shader, bodyTexture);
+ var roofNode = new SceneNode(roofObj);
+ roofNode.Position = new Vector3(0.0f, 0.25f, 0.0f);
+ roofNode.Scale = new Vector3(0.5f, 1.5f, .25f);
+ roofNode.Rotation = Quaternion.FromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(90.0f));
+ roofNode.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(90.0f));
+ MainNode.AddChild(roofNode);
- bodyObject.Position = new Vector3(0.0f, 0.0f, 0.0f);
- bodyObject.Scale = new Vector3(1.5f, 0.5f, 0.5f);
+ // Building the wheels
- bodyObject.Draw(view, projection);
- }
-
- private void drawRoof(Matrix4 view, Matrix4 projection)
- {
- Mesh roofMesh = ShapeFactory.CreateTexturedCylinder();
- RenderObject roofObject = new RenderObject(roofMesh, _wheelShader, _bodyTexture);
-
- roofObject.Position = new Vector3(0.0f, 0.25f, 0.0f);
- roofObject.Scale = new Vector3(0.5f, 1.5f, .25f);
-
- roofObject.Rotation = Quaternion.FromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(90.0f));
- roofObject.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(90.0f));
-
-
-
- roofObject.Draw(view, projection);
- }
-
- public void DrawBus(Matrix4 view, Matrix4 projection)
- {
- // Drawing 4 wheels
float xOffset = 0.4f; // Reduced to bring wheels closer to the body
float zOffset = 0.28f; // Reduced to bring front and back wheels closer
float yOffset = -0.3f; // Adjusted to ensure wheels touch the body
-
- // Drawing 4 wheels
- for (int i = 0; i < 4; i++)
- {
- float xPosition = (i % 2 == 0) ? -xOffset : xOffset; // Left or Right
- float zPosition = (i < 2) ? zOffset : -zOffset; // Front or Back
- DrawWheel(view, projection, new Vector3(xPosition, yOffset, zPosition));
- }
+ Vector3[] wheelPositions =
+ {
+ new Vector3(-xOffset, yOffset, zOffset), // Front Left
+ new Vector3(xOffset, yOffset, zOffset), // Front Right
+ new Vector3(-xOffset, yOffset, -zOffset), // Back Left
+ new Vector3(xOffset, yOffset, -zOffset) // Back Right
+ };
- // Drawing the body
- drawBody(view, projection);
- // Drawing the roof
- drawRoof(view, projection);
+ foreach (var pos in wheelPositions)
+ {
+ var wheelObj = new RenderObject(_wheelMesh, shader, wheelTexture);
+ var wheelNode = new SceneNode(wheelObj);
+
+ wheelNode.Position = pos; // Relative to the MainNode!
+ wheelNode.Scale = new Vector3(0.3f, 0.1f, 0.2f);
+ // Rotate cylinder to act like a wheel
+ wheelNode.Rotation = Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(90.0f));
+
+ MainNode.AddChild(wheelNode);
+ }
+
+ }
+
+
+ public void Draw(Matrix4 view, Matrix4 projection)
+ {
+ MainNode.Draw(view, projection, Matrix4.Identity);
}
diff --git a/TheRepo/TheLabs/Texture.cs b/TheRepo/TheLabs/Texture.cs
index bd171ff..0c64ac3 100644
--- a/TheRepo/TheLabs/Texture.cs
+++ b/TheRepo/TheLabs/Texture.cs
@@ -18,7 +18,6 @@ public class Texture : IDisposable
GL.BindTexture(TextureTarget.Texture2D, Handle);
// --- Set texture parameters ---
- // Repeat the texture if UVs go outside [0, 1]
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
diff --git a/TheRepo/TheLabs/TheLabs.csproj b/TheRepo/TheLabs/TheLabs.csproj
index b218602..6b70cc0 100644
--- a/TheRepo/TheLabs/TheLabs.csproj
+++ b/TheRepo/TheLabs/TheLabs.csproj
@@ -8,6 +8,7 @@
+
diff --git a/TheRepo/VectorAndMatrixTests/VectorAndMatrixTests.csproj b/TheRepo/VectorAndMatrixTests/VectorAndMatrixTests.csproj
index 73786e6..7e03be5 100644
--- a/TheRepo/VectorAndMatrixTests/VectorAndMatrixTests.csproj
+++ b/TheRepo/VectorAndMatrixTests/VectorAndMatrixTests.csproj
@@ -10,6 +10,7 @@
+