Watch
2
0
Fork
You've already forked raylib-cs
0
raylib-cs/Examples/Models/MeshGeneration.cs
2026-07-17 07:49:07 +02:00

230 lines
7.4 KiB
C#

/*******************************************************************************************
*
* raylib [models] example - mesh generation
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.8, last time updated with raylib 4.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Models;
public partial class MeshGeneration : IExample
{
private const int screenWidth = 800;
private const int screenHeight = 450;
public string Name => "Models / Mesh Generation";
public string Title => "raylib [models] example - mesh generation";
private Texture2D texture;
private Model[] models;
private Camera3D camera;
private Vector3 position;
private int currentModel;
public void Init()
{
// We generate a checked image for texturing
var isChecked = GenImageChecked(2, 2, 1, 1, Color.Red, Color.Green);
texture = LoadTextureFromImage(isChecked);
UnloadImage(isChecked);
models = new Model[9];
models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 4, 3));
models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f));
models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32));
models[3] = LoadModelFromMesh(GenMeshHemiSphere(2, 16, 16));
models[4] = LoadModelFromMesh(GenMeshCylinder(1, 2, 16));
models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32));
models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128));
models[7] = LoadModelFromMesh(GenMeshPoly(5, 2.0f));
models[8] = LoadModelFromMesh(GenMeshCustom());
// NOTE: Generated meshes could be exported using ExportMesh()
// Set checked texture as default diffuse component for all models material
for (var i = 0; i < models.Length; i++)
{
// Set map diffuse texture
Raylib.SetMaterialTexture(ref models[i], 0, MaterialMapIndex.Albedo, ref texture);
}
// Define the camera to look into our 3d world
camera = new();
camera.Position = new Vector3(5.0f, 5.0f, 5.0f);
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
camera.FovY = 45.0f;
camera.Projection = CameraProjection.Perspective;
// Model drawing position
position = new(0.0f, 0.0f, 0.0f);
currentModel = 0;
}
public void Update()
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(ref camera, CameraMode.Orbital);
if (IsMouseButtonPressed(MouseButton.Left))
{
currentModel = (currentModel + 1) % models.Length; // Cycle between the textures
}
if (IsKeyPressed(KeyboardKey.Right))
{
currentModel++;
if (currentModel >= models.Length)
{
currentModel = 0;
}
}
else if (IsKeyPressed(KeyboardKey.Left))
{
currentModel--;
if (currentModel < 0)
{
currentModel = models.Length - 1;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(Color.RayWhite);
BeginMode3D(camera);
DrawModel(models[currentModel], position, 1.0f, Color.White);
DrawGrid(10, 1.0f);
EndMode3D();
DrawRectangle(30, 400, 310, 30, Fade(Color.SkyBlue, 0.5f));
DrawRectangleLines(30, 400, 310, 30, Fade(Color.DarkBlue, 0.5f));
DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, Color.Blue);
switch (currentModel)
{
case 0:
DrawText("PLANE", 680, 10, 20, Color.DarkBlue);
break;
case 1:
DrawText("CUBE", 680, 10, 20, Color.DarkBlue);
break;
case 2:
DrawText("SPHERE", 680, 10, 20, Color.DarkBlue);
break;
case 3:
DrawText("HEMISPHERE", 640, 10, 20, Color.DarkBlue);
break;
case 4:
DrawText("CYLINDER", 680, 10, 20, Color.DarkBlue);
break;
case 5:
DrawText("TORUS", 680, 10, 20, Color.DarkBlue);
break;
case 6:
DrawText("KNOT", 680, 10, 20, Color.DarkBlue);
break;
case 7:
DrawText("POLY", 680, 10, 20, Color.DarkBlue);
break;
case 8:
DrawText("Custom (triangle)", 580, 10, 20, Color.DarkBlue);
break;
default:
break;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
public void Unload()
{
UnloadTexture(texture); // Unload texture
// Unload models data (GPU VRAM)
for (var i = 0; i < models.Length; i++)
{
UnloadModel(models[i]);
}
}
// Generate a simple triangle mesh from code
private static Mesh GenMeshCustom()
{
Mesh mesh = new(3, 1);
mesh.AllocVertices();
mesh.AllocTexCoords();
mesh.AllocNormals();
var vertices = mesh.VerticesAs<Vector3>();
var texcoords = mesh.TexCoordsAs<Vector2>();
var normals = mesh.NormalsAs<Vector3>();
// Vertex at (0, 0, 0)
vertices[0] = new(0, 0, 0);
normals[0] = new(0, 1, 0);
texcoords[0] = new(0, 0);
// Vertex at (1, 0, 2)
vertices[1] = new(1, 0, 2);
normals[1] = new(0, 1, 0);
texcoords[1] = new(0.5f, 1.0f);
// Vertex at (2, 0, 0)
vertices[2] = new(2, 0, 0);
normals[2] = new(0, 1, 0);
texcoords[2] = new(1, 0);
// Upload mesh data from CPU (RAM) to GPU (VRAM) memory
UploadMesh(ref mesh, false);
return mesh;
}
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation");
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
var game = new MeshGeneration();
game.Init();
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
game.Update();
}
game.Unload();
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
}