Skip to main content

Overview

Atlas Engine uses a flexible component-based architecture where game objects can have behaviors and properties attached through components. The main object types are CoreObject, Model, and CompoundObject.

CoreObject

CoreObject is the fundamental 3D object class that represents renderable geometry in the scene.

Creating Objects

Atlas provides helper functions for creating common shapes:
object.h:655-715
// Create a box
CoreObject cube = createBox({1.0f, 1.0f, 1.0f}, Color::red());

// Create a sphere
CoreObject sphere = createSphere(0.5f, 36, 18, Color::blue());

// Create a plane
CoreObject plane = createPlane({10.0f, 10.0f}, Color::white());

// Create a pyramid
CoreObject pyramid = createPyramid({1.0f, 1.0f, 1.0f}, Color::green());

// Create debug objects (with default texture and physics)
CoreObject debugBox = createDebugBox({1.0f, 1.0f, 1.0f});
CoreObject debugSphere = createDebugSphere(0.5f);

Object Properties

object.h:385-395
// Position
cube.setPosition({0.0f, 1.0f, 0.0f});
cube.move({0.0f, 0.1f, 0.0f});  // Relative movement
Position3d pos = cube.getPosition();

// Rotation
cube.setRotation({0.0f, 45.0f, 0.0f});  // Euler angles
cube.rotate({0.0f, 1.0f, 0.0f});        // Relative rotation
cube.lookAt({0.0f, 0.0f, 0.0f});        // Look at target

// Scale
cube.setScale({2.0f, 2.0f, 2.0f});
Size3d scale = cube.getScale();

Material Properties

object.h:48-65
// PBR material
cube.material.albedo = Color::red();
cube.material.metallic = 0.8f;   // 0.0 = dielectric, 1.0 = metal
cube.material.roughness = 0.3f;  // 0.0 = smooth, 1.0 = rough
cube.material.ao = 1.0f;         // Ambient occlusion

Textures

object.h:349-350
// Load texture from resource
Texture albedoTex = Texture::fromResource(
    Workspace::get().createResource("brick.png", "Brick", ResourceType::Image)
);
albedoTex.type = TextureType::Color;
cube.attachTexture(albedoTex);

// Normal map
Texture normalMap = Texture::fromResource(
    Workspace::get().createResource("brick_normal.png", "BrickNormal", ResourceType::Image)
);
normalMap.type = TextureType::Normal;
cube.attachTexture(normalMap);

Shaders

object.h:344-346
// Use default shaders
VertexShader vs = VertexShader::fromDefaultShader(AtlasVertexShader::Main);
FragmentShader fs = FragmentShader::fromDefaultShader(AtlasFragmentShader::Main);
vs.compile();
fs.compile();
cube.createAndAttachProgram(vs, fs);

// Or attach existing program
ShaderProgram program = ShaderProgram::fromDefaultShaders(
    AtlasVertexShader::Main, 
    AtlasFragmentShader::Main
);
cube.attachProgram(program);

Initialization

object.h:354
// Must call initialize before adding to window
cube.initialize();
window.addObject(&cube);

Instancing

Efficiently render multiple copies of an object:
test/main.cpp:33-36
for (int i = 0; i < 6; i++) {
    Instance &instance = cube.createInstance();
    instance.move({0.0f, 0.6f * i, 0.0f});
}
object.h:511-521
// Instance properties
Instance &inst = cube.createInstance();
inst.setPosition({2.0f, 0.0f, 0.0f});
inst.setRotation({0.0f, 45.0f, 0.0f});
inst.setScale({1.5f, 1.5f, 1.5f});
inst.move({0.1f, 0.0f, 0.0f});
inst.rotate({0.0f, 1.0f, 0.0f});
inst.scaleBy({1.1f, 1.1f, 1.1f});

Rendering Options

object.h:458-504
// Shadow casting
cube.castsShadows = true;

// Deferred vs forward rendering
cube.useDeferredRendering = true;     // Use deferred pipeline
cube.disableDeferredRendering();      // Force forward rendering

// Visibility
cube.show();
cube.hide();

Emissive Objects

object.h:322
// Make object emit light
cube.makeEmissive(&scene, Color(1.0f, 0.8f, 0.6f), 2.0f);

Model

The Model class loads and manages 3D models from files:
object.h:750
// Load model from resource
Resource modelRes = Workspace::get().createResource(
    "models/backpack.obj", "Backpack", ResourceType::Model
);

Model backpack;
backpack.fromResource(modelRes);
backpack.setPosition({0.0f, 0.0f, 0.0f});
backpack.setScale({0.5f, 0.5f, 0.5f});
backpack.initialize();
window.addObject(&backpack);

Model Operations

object.h:764-806
// Transform entire model
backpack.move({1.0f, 0.0f, 0.0f});
backpack.setPosition({0.0f, 1.0f, 0.0f});
backpack.setRotation({0.0f, 90.0f, 0.0f});
backpack.setScale({2.0f, 2.0f, 2.0f});

// Apply texture to all meshes
Texture modelTexture = Texture::fromResource("texture.png");
backpack.attachTexture(modelTexture);

// Material
backpack.material.metallic = 0.5f;
backpack.material.roughness = 0.7f;

// Rendering mode
backpack.useDeferredRendering = true;

// Access individual objects
std::vector<std::shared_ptr<CoreObject>> objects = backpack.getObjects();

CompoundObject

CompoundObject allows you to create complex objects composed of multiple CoreObject instances:
test/main.cpp:22-43
class SphereCube : public CompoundObject {
    CoreObject sphere;
    CoreObject cube;

public:
    void init() override {
        cube = createDebugBox({0.5f, 0.5f, 0.5f});
        cube.setPosition({-1.0f, cube.getPosition().y, 0.0f});
        cube.initialize();
        this->addObject(&cube);

        for (int i = 0; i < 6; i++) {
            Instance &instance = cube.createInstance();
            instance.move({0.0f, 0.6f * i, 0.0f});
        }

        sphere = createDebugSphere(0.25f);
        sphere.setPosition({1.0f, sphere.getPosition().y, 0.0f});
        sphere.initialize();
        this->addObject(&sphere);
    }
};

Using CompoundObject

SphereCube compound;
compound.init();
compound.initialize();
compound.setPosition({0.0f, 2.0f, 0.0f});
window.addObject(&compound);

Advanced CompoundObject Example

test/main.cpp:79-114
class WaterPot : public CompoundObject {
    CoreObject pot;
    Fluid water;

public:
    void init() override {
        pot = createBox({1.0f, 0.25f, 0.25f}, Color(0.6f, 0.4f, 0.2f));

        Instance &potRight = pot.createInstance();
        potRight.move({0.0f, 0.0f, 1.0f});
        Instance &potDown = pot.createInstance();
        potDown.rotate({0.0f, 90.0f, 0.0f});
        potDown.move({-0.5f, 0.0f, 0.5f});
        Instance &potUp = pot.createInstance();
        potUp.rotate({0.0f, -90.0f, 0.0f});
        potUp.move({0.5f, 0.0f, 0.5f});
        pot.initialize();
        this->addObject(&pot);

        Texture waterDUDV = Texture::fromResource(
            Workspace::get().createResource(
                "water_dudv.png", "WaterDUDV", ResourceType::Image));

        Texture waterNormal = Texture::fromResource(
            Workspace::get().createResource(
                "water_normal.png", "WaterNormal", ResourceType::Image));

        water = Fluid();
        water.create({0.9, 0.9}, Color::blue());
        water.setPosition({0.0f, 0.10f, 0.5f});
        water.movementTexture = waterDUDV;
        water.normalTexture = waterNormal;
        water.initialize();
        this->addObject(&water);
    }
};

Component System

Components add behavior and functionality to game objects:

Creating Components

test/main.cpp:53-65
class HorizontalMover : public Component {
private:
    float phase = 0.0f;

public:
    void update(float deltaTime) override {
        float amplitude = 0.01f;
        float frequency = 4.0f;
        phase += deltaTime * frequency * 2.0f * M_PI;
        float position = amplitude * sin(phase);
        object->move({position, 0.0f, 0.0f});
    }
};

Component Lifecycle

component.h:56-88
class MyComponent : public Component {
public:
    // Called when component is attached
    void atAttach() override {
        // Setup code
    }
    
    // Called once after attachment
    void init() override {
        // Initialization code
    }
    
    // Called before physics update
    void beforePhysics() override {
        // Pre-physics logic
    }
    
    // Called every frame
    void update(float deltaTime) override {
        // Update logic
    }
    
    // Called when view matrix changes
    void setViewMatrix(const glm::mat4 &view) override {
        // View update logic
    }
    
    // Called when projection matrix changes
    void setProjectionMatrix(const glm::mat4 &projection) override {
        // Projection update logic
    }
};

Adding Components

object.h:467-487
// Create and add component
HorizontalMover mover;
cube.addComponent(mover);

// Or add as shared_ptr
auto mover = std::make_shared<HorizontalMover>();
cube.addComponent(mover);

Accessing Components

component.h:397-407
// Get component by type
auto mover = cube.getComponent<HorizontalMover>();
if (mover) {
    // Use component
}

Component Access to GameObject

component.h:123
class MyComponent : public Component {
    void update(float deltaTime) override {
        // Access parent object
        object->move({1.0f, 0.0f, 0.0f});
        
        // Access window
        Window* window = getWindow();
        
        // Get other components
        auto other = object->getComponent<OtherComponent>();
    }
};

TraitComponent

Type-safe components that work only with specific object types:
test/main.cpp:45-51
class FPSTextUpdater : public TraitComponent<Text> {
public:
    void updateComponent(Text *object) override {
        int fps = static_cast<int>(getWindow()->getFramesPerSecond());
        object->content = "FPS: " + std::to_string(fps);
    }
};

// Add trait component
fpsText.addTraitComponent<Text>(FPSTextUpdater());

Component Examples

Audio Component

test/main.cpp:67-77
class BackpackAttach : public Component {
public:
    void init() override {
        auto player = this->object->getComponent<AudioPlayer>();
        player->setSource(Workspace::get().createResource(
            "exampleMP3.mp3", "ExampleAudio", ResourceType::Audio));
        player->useSpatialization();
        player->source->setLooping(true);
        player->play();
    }
};

Physics Component

test/main.cpp:116-132
class BallBehavior : public Component {
public:
    void init() override {
        if (object && object->rigidbody) {
            object->rigidbody->applyImpulse({0.0f, 0.0f, 20.0f});
        }
    }
    
    void update(float) override {
        if (Window::mainWindow->isKeyClicked(Key::N)) {
            auto hinge = object->getComponent<HingeJoint>();
            if (hinge) {
                std::cout << "Breaking hinge joint\n";
                hinge->breakJoint();
            }
        }
    }
};

Collision Events

Objects receive collision callbacks:
component.h:103-114
class CollisionHandler : public Component {
public:
    void onCollisionEnter(GameObject *other) override {
        // Collision started
    }
    
    void onCollisionStay(GameObject *other) override {
        // Collision ongoing
    }
    
    void onCollisionExit(GameObject *other) override {
        // Collision ended
    }
};

Signal System

Objects can send and receive signals:
component.h:109-113
class SignalReceiver : public Component {
public:
    void onSignalRecieve(const std::string &signal, GameObject *sender) override {
        if (signal == "damage") {
            // Handle damage
        }
    }
    
    void onSignalEnd(const std::string &signal, GameObject *sender) override {
        // Signal ended
    }
};

GameObject Hierarchy

component.h:418-420
// Add dependencies
player.addDependency(&weapon);
player.addDependency(&armor);

// Get dependencies
std::vector<GameObject*> deps = player.getDependencies();

Object IDs

component.h:414
// Each object has a unique ID
unsigned int id = object.getId();

// Access object by ID
GameObject* obj = atlas::gameObjects[id];

Example: Complete Object Setup

// Create object
CoreObject player = createBox({1.0f, 2.0f, 1.0f}, Color::blue());

// Set transform
player.setPosition({0.0f, 1.0f, 0.0f});
player.setScale({0.5f, 1.0f, 0.5f});

// Configure material
player.material.albedo = Color::blue();
player.material.metallic = 0.2f;
player.material.roughness = 0.8f;

// Add texture
Texture playerTexture = Texture::fromResource(
    Workspace::get().createResource("player.png", "PlayerTex", ResourceType::Image)
);
player.attachTexture(playerTexture);

// Add shaders
VertexShader vs = VertexShader::fromDefaultShader(AtlasVertexShader::Main);
FragmentShader fs = FragmentShader::fromDefaultShader(AtlasFragmentShader::Main);
vs.compile();
fs.compile();
player.createAndAttachProgram(vs, fs);

// Add components
PlayerController controller;
player.addComponent(controller);

HealthComponent health;
player.addComponent(health);

// Initialize and add to scene
player.initialize();
window.addObject(&player);

Next Steps

Physics

Add physics simulation to your objects

Lighting

Learn about lighting objects

Audio

Add spatial audio to objects

Textures

Work with textures and materials

Build docs developers (and LLMs) love