raylib-go/examples/models/m3d_loading/main.go
2025-06-22 17:48:18 -04:00

155 lines
4.3 KiB
Go

/*******************************************************************************************
*
* raylib [models] example - Load models M3D
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by bzt (@bztsrc) and reviewed by Ramon Santamaria (@raysan5)
*
* NOTES:
* - Model3D (M3D) fileformat specs: https://gitlab.com/bztsrc/model3d
* - Bender M3D exported: https://gitlab.com/bztsrc/model3d/-/tree/master/blender
*
* 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) 2022-2024 bzt (@bztsrc)
*
********************************************************************************************/
package main
import (
rl "git.terah.dev/UnrealXR/raylib-go/raylib"
)
const (
screenWidth = 800
screenHeight = 450
)
func main() {
// Initialization
rl.InitWindow(screenWidth, screenHeight, "raylib [models] example - M3D model loading")
// Define the camera to look into our 3d world
camera := rl.Camera{
Position: rl.NewVector3(1.5, 1.5, 1.5),
Target: rl.NewVector3(0.0, 0.4, 0.0),
Up: rl.NewVector3(0.0, 1.0, 0.0),
Fovy: 45.0,
Projection: rl.CameraPerspective,
}
position := rl.NewVector3(0.0, 0.0, 0.0)
modelFileName := "cesium_man.m3d"
drawMesh := true
drawSkeleton := true
animPlaying := false // Store anim state, what to draw
// Load model
model := rl.LoadModel(modelFileName)
// Load animations
animFrameCounter := 0
animID := 0
anims := rl.LoadModelAnimations(modelFileName)
animsCount := int32(len(anims))
rl.DisableCursor()
rl.SetTargetFPS(60)
// Main game loop
for !rl.WindowShouldClose() {
// Update
rl.UpdateCamera(&camera, rl.CameraFirstPerson)
if animsCount > 0 {
// Play animation when space bar is held down (or step one frame with N)
if rl.IsKeyDown(rl.KeySpace) || rl.IsKeyPressed(rl.KeyN) {
animFrameCounter++
if animFrameCounter >= int(anims[animID].FrameCount) {
animFrameCounter = 0
}
rl.UpdateModelAnimation(model, anims[animID], int32(animFrameCounter))
animPlaying = true
}
// Select animation by pressing C
if rl.IsKeyPressed(rl.KeyC) {
animFrameCounter = 0
animID++
if animID >= int(animsCount) {
animID = 0
}
rl.UpdateModelAnimation(model, anims[animID], 0)
animPlaying = true
}
}
// Toggle skeleton drawing
if rl.IsKeyPressed(rl.KeyB) {
drawSkeleton = !drawSkeleton
}
// Toggle mesh drawing
if rl.IsKeyPressed(rl.KeyM) {
drawMesh = !drawMesh
}
// Draw
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.BeginMode3D(camera)
// Draw 3d model with texture
if drawMesh {
rl.DrawModel(model, position, 1.0, rl.White)
}
// Draw the animated skeleton
if drawSkeleton {
modelBones := model.GetBones()
modelPoses := model.GetBindPose()
anim := anims[animID]
animBones := anim.GetBones()
for bone := 0; bone < int(model.BoneCount)-1; bone++ {
if !animPlaying || animsCount == 0 {
// Display the bind-pose skeleton
rl.DrawCube(modelPoses[bone].Translation, 0.04, 0.04, 0.04, rl.Red)
if modelBones[bone].Parent >= 0 {
rl.DrawLine3D(modelPoses[bone].Translation, modelPoses[modelBones[bone].Parent].Translation, rl.Red)
}
} else {
// // Display the frame-pose skeleton
pos := anim.GetFramePose(animFrameCounter, bone).Translation
rl.DrawCube(pos, 0.05, 0.05, 0.05, rl.Red)
if animBones[bone].Parent >= 0 {
endPos := anim.GetFramePose(animFrameCounter, int(animBones[bone].Parent)).Translation
rl.DrawLine3D(pos, endPos, rl.Red)
}
}
}
}
rl.DrawGrid(10, 1.0)
rl.EndMode3D()
rl.DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, screenHeight-80, 10, rl.Maroon)
rl.DrawText("PRESS N to STEP ONE ANIMATION FRAME", 10, screenHeight-60, 10, rl.DarkGray)
rl.DrawText("PRESS C to CYCLE THROUGH ANIMATIONS", 10, screenHeight-40, 10, rl.DarkGray)
rl.DrawText("PRESS M to toggle MESH, B to toggle SKELETON DRAWING", 10, screenHeight-20, 10, rl.DarkGray)
rl.DrawText("(c) CesiumMan model by KhronosGroup", screenWidth-210, screenHeight-20, 10, rl.Gray)
rl.EndDrawing()
}
// De-Initialization
rl.UnloadModelAnimations(anims)
rl.UnloadModel(model)
rl.CloseWindow()
}