如何在Raylib中创建带厚度的3D三角形
Problem Description
I've been able to create a 3D triangle in Raylib, but now I want to add thickness to it. How can I achieve this using Raylib? Below is my C# code that renders a single flat triangle without thickness:
using System; using Raylib_cs; using System.Numerics; namespace Triangle { class Program { static void Main(string[] args) { Raylib.InitWindow(800, 480, "Hello World"); Camera3D camera; camera.position = new Vector3(10.0f, 10.0f, 10.0f); // Camera3D position camera.target = new Vector3(0.0f, 0.0f, 0.0f); // Camera3D looking at point camera.up = new Vector3(0.0f, 1.0f, 0.0f); // Camera3D up vector (rotation towards target) camera.fovy = 120.0f; // Camera3D field-of-view Y camera.type = CameraType.CAMERA_PERSPECTIVE; // Camera3D mode type Vector3 point1 = new Vector3(0.0f, 0.0f, 0.0f); Vector3 point2 = new Vector3(10.0f, 0.0f, 0.0f); Vector3 point3 = new Vector3(10.0f, 10.0f, 0.0f); Raylib.SetCameraMode(camera, CameraMode.CAMERA_FREE); // Set a free camera mode Raylib.SetTargetFPS(60); Rlgl.rlDisableBackfaceCulling(); while (!Raylib.WindowShouldClose()) { Raylib.UpdateCamera(ref camera); Raylib.BeginDrawing(); Raylib.ClearBackground(Color.RAYWHITE); Raylib.BeginMode3D(camera); Raylib.DrawTriangle3D(point1, point2, point3, Color.BLACK); Raylib.EndMode3D(); //text Raylib.DrawRectangle(10, 10, 320, 133, Raylib.ColorAlpha(Color.SKYBLUE, 0.5f)); Raylib.DrawRectangleLines(10, 10, 320, 133, Color.BLUE); Raylib.DrawText("Free camera default controls:", 20, 20, 10, Color.BLACK); Raylib.DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, Color.DARKGRAY); Raylib.DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, Color.DARKGRAY); Raylib.DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, Color.DARKGRAY); Raylib.DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, Color.DARKGRAY); Raylib.EndDrawing(); } Raylib.CloseWindow(); } } }
Solution
Great question! Adding thickness to a flat 3D triangle means converting it into a triangular prism—you'll create a second triangle parallel to the original, then connect their corresponding vertices to form the side faces. Here's how to modify your code step by step:
Step 1: Calculate the triangle's normal vector
The normal vector points perpendicular to the triangle's plane, which we'll use to offset the second triangle. We compute this via the cross product of two triangle edges, then normalize it to a unit vector (so it doesn't scale our offset unexpectedly).
Step 2: Create offset vertices for the parallel triangle
Multiply the normalized normal vector by your desired thickness value, then add this offset to each original vertex to get the three vertices of the back face of the prism.
Step 3: Draw all prism faces
You need to render:
- The original front triangle
- The offset back triangle
- Three rectangular side faces (split into two triangles each, since Raylib only renders triangular primitives)
Here's the fully modified code:
using System; using Raylib_cs; using System.Numerics; namespace Triangle { class Program { static void Main(string[] args) { Raylib.InitWindow(800, 480, "Thick 3D Triangle"); Camera3D camera; camera.position = new Vector3(10.0f, 10.0f, 10.0f); camera.target = new Vector3(0.0f, 0.0f, 0.0f); camera.up = new Vector3(0.0f, 1.0f, 0.0f); camera.fovy = 120.0f; camera.type = CameraType.CAMERA_PERSPECTIVE; // Original triangle vertices Vector3 point1 = new Vector3(0.0f, 0.0f, 0.0f); Vector3 point2 = new Vector3(10.0f, 0.0f, 0.0f); Vector3 point3 = new Vector3(10.0f, 10.0f, 0.0f); // Adjust this value to control how thick the prism is float thickness = 2.0f; // Calculate edges of the original triangle Vector3 edge1 = point2 - point1; Vector3 edge2 = point3 - point1; // Compute and normalize the normal vector Vector3 normal = Vector3.Cross(edge1, edge2); normal = Vector3.Normalize(normal); // Create offset vertices for the back triangle Vector3 point1Offset = point1 + normal * thickness; Vector3 point2Offset = point2 + normal * thickness; Vector3 point3Offset = point3 + normal * thickness; Raylib.SetCameraMode(camera, CameraMode.CAMERA_FREE); Raylib.SetTargetFPS(60); Rlgl.rlDisableBackfaceCulling(); // Ensures all faces are visible while (!Raylib.WindowShouldClose()) { Raylib.UpdateCamera(ref camera); Raylib.BeginDrawing(); Raylib.ClearBackground(Color.RAYWHITE); Raylib.BeginMode3D(camera); // Draw front triangle Raylib.DrawTriangle3D(point1, point2, point3, Color.BLACK); // Draw back triangle (reversed vertex order to fix face orientation) Raylib.DrawTriangle3D(point1Offset, point3Offset, point2Offset, Color.DARKGRAY); // Draw side faces (each rectangle split into two triangles) // Side 1: Connect point1 -> point2 -> point2Offset -> point1Offset Raylib.DrawTriangle3D(point1, point2, point2Offset, Color.GRAY); Raylib.DrawTriangle3D(point1, point2Offset, point1Offset, Color.GRAY); // Side 2: Connect point2 -> point3 -> point3Offset -> point2Offset Raylib.DrawTriangle3D(point2, point3, point3Offset, Color.GRAY); Raylib.DrawTriangle3D(point2, point3Offset, point2Offset, Color.GRAY); // Side 3: Connect point3 -> point1 -> point1Offset -> point3Offset Raylib.DrawTriangle3D(point3, point1, point1Offset, Color.GRAY); Raylib.DrawTriangle3D(point3, point1Offset, point3Offset, Color.GRAY); Raylib.EndMode3D(); // Control instructions Raylib.DrawRectangle(10, 10, 320, 143, Raylib.ColorAlpha(Color.SKYBLUE, 0.5f)); Raylib.DrawRectangleLines(10, 10, 320, 143, Color.BLUE); Raylib.DrawText("Free camera default controls:", 20, 20, 10, Color.BLACK); Raylib.DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, Color.DARKGRAY); Raylib.DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, Color.DARKGRAY); Raylib.DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, Color.DARKGRAY); Raylib.DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, Color.DARKGRAY); Raylib.DrawText($"Current thickness: {thickness}", 20, 120, 10, Color.BLACK); Raylib.EndDrawing(); } Raylib.CloseWindow(); } } }
Key Notes:
- Normal Vector: The cross product gives a direction perpendicular to the triangle. Normalizing ensures our offset only uses the direction, not the length of the edge vectors.
- Back Triangle Order: Reversing the vertex order for the back face ensures it renders correctly (even with backface culling disabled, this helps with consistent lighting if you add it later).
- Side Faces: Raylib doesn't have a 3D rectangle primitive, so we split each side into two triangles to fill the area.
- Thickness Control: Just tweak the
thicknessvariable to make the prism thicker or thinner.
内容的提问来源于stack exchange,提问作者Nikola Petrovic

