Skip to content

Models ​

The Models module handles loading, storing, and creating instances of 3D models in various formats.

Import ​

javascript
import { Models } from 'mage-engine';

Supported Formats ​

FormatExtensionFeatures
glTF.gltfModern, recommended, supports animations
glTF Binary.glbCompressed single-file glTF
FBX.fbxAutodesk format, good animation support
OBJ.objSimple geometry, no animations
JSON.jsonThree.js JSON format

Asset Configuration ​

Define models in your assets configuration:

javascript
const assets = {
    models: {
        'car': 'models/car.gltf',
        'character': 'models/character.fbx',
        'rock': 'models/rock.obj'
    },
    // Level-specific models
    '/forest': {
        models: {
            'tree': 'models/tree.glb'
        }
    }
};

Creating Model Instances ​

Models.create(name, options) ​

Create an element from a loaded model.

javascript
const car = Models.create('car');
car.setPosition({ x: 0, y: 0, z: 0 });

Options ​

ParameterTypeDescription
namestringUnique name for this instance
javascript
const car1 = Models.create('car', { name: 'playerCar' });
const car2 = Models.create('car', { name: 'enemyCar' });

Basic Example ​

javascript
import { Level, Models } from 'mage-engine';

class GameLevel extends Level {
    onCreate() {
        // Create player car
        this.player = Models.create('car', { name: 'player' });
        this.player.setPosition({ x: 0, y: 1, z: 0 });
        this.player.setRotation({ y: Math.PI / 2 });
        this.player.setScale(2);
    }
}

Animated Models ​

FBX and glTF models can contain animations:

javascript
const character = Models.create('character');

// List available animations
const animations = character.getAvailableAnimations();
console.log(animations);  // ['idle', 'walk', 'run', 'jump']

// Play animation
character.playAnimation('idle');

// Play with options
character.playAnimation('walk', {
    loop: THREE.LoopRepeat,
    duration: 0.3  // Crossfade duration
});

// Stop animation
character.stopAnimation();

Model Hierarchy ​

Access child objects within models:

javascript
const car = Models.create('car');

// Get wheel by name (defined in modeling software)
const frontLeftWheel = car.getObjectByName('wheel_FL');

// Traverse all children
car.traverse((child) => {
    if (child.isMesh) {
        console.log('Found mesh:', child.name);
    }
});

Materials ​

Modify model materials:

javascript
const car = Models.create('car');

// Set color on all meshes
car.setColor(0xff0000);

// Set opacity
car.setOpacity(0.5);

// Apply texture
car.setTexture('map', 'carTexture');

// Access specific material
car.traverse((child) => {
    if (child.isMesh && child.name === 'body') {
        child.material.metalness = 0.9;
        child.material.roughness = 0.1;
    }
});

Multiple Instances ​

javascript
class ForestLevel extends Level {
    onCreate() {
        // Create many trees
        for (let i = 0; i < 100; i++) {
            const tree = Models.create('tree', { name: `tree_${i}` });
            tree.setPosition({
                x: Math.random() * 100 - 50,
                y: 0,
                z: Math.random() * 100 - 50
            });
            tree.setScale(0.8 + Math.random() * 0.4);
            tree.setRotation({ y: Math.random() * Math.PI * 2 });
        }
    }
}

Physics Integration ​

Add physics to models:

javascript
import { Models, Physics, PHYSICS_TYPES } from 'mage-engine';

const crate = Models.create('crate');
crate.setPosition({ x: 0, y: 10, z: 0 });

// Add physics body
Physics.add(crate, {
    mass: 10,
    type: PHYSICS_TYPES.BOX
});

Loading States ​

javascript
class LoadingLevel extends Level {
    onCreate() {
        // Check if model loaded
        if (Models.has('character')) {
            this.createCharacter();
        } else {
            // Handle missing model
            console.error('Character model not loaded');
        }
    }
}

Complete Example ​

javascript
import { Level, Models, Scene, ENTITY_EVENTS } from 'mage-engine';

class CharacterLevel extends Level {
    onCreate() {
        // Create animated character
        this.character = Models.create('character', { name: 'hero' });
        this.character.setPosition({ x: 0, y: 0, z: 0 });
        this.character.setScale(0.01);  // Scale down if needed
        
        // Start idle animation
        this.character.playAnimation('idle');
        
        // Listen for animation events
        this.character.addEventListener(ENTITY_EVENTS.ANIMATION.FINISHED, () => {
            this.character.playAnimation('idle');
        });
        
        // Setup camera to follow
        Scene.getCamera().addScript('SmoothFollow', {
            target: this.character
        });
    }
    
    update(dt) {
        // Update character logic
    }
}

Best Practices ​

  1. Use glTF/GLB for best compatibility and features
  2. Optimize models before export (reduce polygons, bake textures)
  3. Name objects in your modeling software for easy access
  4. Use instancing for many identical objects (handled automatically)
  5. Preload models in asset configuration for seamless gameplay

See Also ​