commit 5afb395e8c694c0261fe531ade8c919b08fc6473 Author: Jason Ly Date: Fri Sep 26 21:25:28 2025 -0400 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..a06eca4 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# joomer-bella-basic-renderer +basic rendering using bella engine sdk + + + +# Demonstrates +- basic rendering +- bella events to monitor render process + +# Usage + +``` +# Compile the program (one long line) +cl /std:c++14 /DNDEBUG /Ibella_engine_sdk\src /EHsc joomer-bella-basic-renderer.cpp ^ + /link /LIBPATH:bella_engine_sdk\lib bella_engine_sdk.lib /OUT:joomer-bella-basic-renderer.exe + +# Set up library path and run +set PATH=%PATH%;bella_engine_sdk\lib +joomer-bella-basic-renderer.exe +``` + +[todo] create makefile + +# Build +``` +learndir/ +└── joomer-bella-basic-renderer/ + └── build_engine_sdk/ +``` + +## MacOS (kasm-monterey) +- [ ] Install Xcode +``` +mkdir learndir +cd learndir +curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-macos.zip +unzip bella_engine_sdk-25.3.0-macos.zip +git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git +cd joomer-bella-basic-renderer +make all -j4 +bin/Darwin/release/poomer-bella-sine -r +open ./joomer-bella-basic-renderer.png +``` + +## Ubuntu Linux (kasm-ubuntu) +``` +sudo apt install -y build-essential curl +mkdir learndir +cd learndir +curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-linux.tar.gz +tar -xvf bella_engine_sdk-25.3.0.tar.gz +git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git +cd joomer-bella-basic-renderer +make all -j4 +bin/Linux/release/joomer-bella-basic-renderer -r +file ./joomer-bella-basic-renderer.png +``` + +## Windows (win10) +- [optioanl] Install https://git-scm.com + +- Download Visual Studio Community Edition 2022 +- Run VisualStudioSetup.exe +- Workload = [x] Desktop developemnt with C++ +- Individial components = [x] Git For Windows + +Run **x64 Native Tools Command Prompt for VS 2022** +``` +cd %USERPROFILE% +mkdir learndir +cd learndir +curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-win32.zip +tar -xf bella_engine_sdk-25.3.0-win32.zip +git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git +cd joomer-bella-basic-renderer +joomer-bella-basic-renderer.exe +start mspaint joomer-bella-basic-renderer.png +``` + diff --git a/joomer-bella-basic-renderer.cpp b/joomer-bella-basic-renderer.cpp new file mode 100644 index 0000000..a9c0aca --- /dev/null +++ b/joomer-bella-basic-renderer.cpp @@ -0,0 +1,161 @@ +#include "bella_engine_sdk/src/bella_sdk/bella_engine.h" // Core rendering engine +#include "bella_engine_sdk/src/bella_sdk/bella_scene.h" // Scene management +#include "bella_engine_sdk/src/dl_core/dl_logging.h" // Logging utilities +#include // For std::this_thread (C++ standard library) +#include // For timing operations (C++ standard library) + +// ============================================================================ +// 🔍 C++ Concept: Observer Pattern +// This lets us "listen" for events from the rendering engine. +// When something happens (rendering starts, progress updates, etc.), +// our functions get called automatically. +// ============================================================================ + +struct MyEngineObserver : public dl::bella_sdk::EngineObserver { + // 🔔 Called when rendering begins + void onStarted(dl::String pass) override { + dl::logInfo("🚀 Rendering started: %s", pass.buf()); + } + + // 🔔 Called repeatedly as rendering progresses (0.0 to 1.0) + void onProgress(dl::String pass, dl::bella_sdk::Progress progress) override { + dl::logInfo("⏳ Progress: %.1f%% - %s", + progress.progress() * 100.0, progress.toString().buf()); + } + + // 🔔 Called when we get the final rendered image + void onImage(dl::String pass, dl::bella_sdk::Image image) override { + dl::logInfo("🖼️ Got image: %dx%d pixels", image.width(), image.height()); + } + + // 🔔 Called when rendering finishes + void onStopped(dl::String pass) override { + dl::logInfo("✅ Rendering complete: %s", pass.buf()); + } +}; + +// ============================================================================ +// 🎬 Main Function: Building Our 3D Scene +// ============================================================================ +int main() { + // Step 1: Create the rendering engine and scene + dl::bella_sdk::Engine engine; // The renderer itself + dl::bella_sdk::Scene scene = engine.scene(); // Container for all our objects + scene.loadDefs(); // Load built-in object types + + // Get the "world" - this is the root of our scene tree + dl::bella_sdk::Node world = scene.world(); + + // ======================================================================== + // 📷 Step 2: Create the Camera System + // Every camera needs: sensor (film) + lens + positioning + // ======================================================================== + + // Create a digital "film" sensor (30mm x 30mm) + dl::bella_sdk::Node sensor = scene.createNode("sensor"); + sensor["size"] = dl::Vec2::make(30.0, 30.0); + + // Create a simple lens (like a magnifying glass) + auto lens = scene.createNode("thinLens"); // 'auto' = let C++ figure out the type + + // Create camera positioning system + the camera itself + auto cameraXform = scene.createNode("xform"); // Transform = position/rotation + cameraXform.parentTo(world); // Attach to our world + + auto camera = scene.createNode("camera"); // The actual camera + camera["resolution"] = dl::Vec2::make(320, 320); // 320x320 pixel image + camera["lens"] = lens; // Connect our lens + camera["sensor"] = sensor; // Connect our sensor + camera.parentTo(cameraXform); // Put camera in the positioning system + + // Tell the scene to use this camera for rendering + auto settings = scene.settings(); + settings["camera"] = camera; + + // ======================================================================== + // ☀️ Step 3: Add Lighting + // ======================================================================== + auto skyDome = scene.createNode("skyDome"); // Simulates sky lighting + skyDome.parentTo(world); + settings["environment"] = skyDome; // Use this for scene lighting + + // ======================================================================== + // 🎨 Step 4: Create Materials (like paint or metal finishes) + // ======================================================================== + + // Golden metal material for our sphere + auto sphereMaterial = scene.createNode("conductor"); // Metal material + sphereMaterial["reflectance"] = dl::Rgba::make(0.8, 0.6, 0.2, 1.0); // Golden color (R,G,B,Alpha) + sphereMaterial["roughness"] = 26.1; // Slightly rough surface + + // Glass-like material for the ground + auto groundMaterial = scene.createNode("dielectric"); // Glass/plastic material + groundMaterial["roughness"] = dl::Real(41.0); // Rough surface + + // ======================================================================== + // 🏀 Step 5: Create Objects (Sphere + Ground) + // ======================================================================== + + // Golden sphere in the center + auto sphereXform = scene.createNode("xform"); // Position controller for sphere + sphereXform["material"] = sphereMaterial; // Apply golden material + sphereXform.parentTo(world); // Add to scene + + auto sphere = scene.createNode("sphere"); // The actual sphere shape + sphere["radius"] = dl::Real(1.0); // 1 unit radius + sphere.parentTo(sphereXform); // Put sphere in its position controller + + // Large disk as ground plane + auto groundXform = scene.createNode("xform"); // Position controller for ground + groundXform["name"] = dl::String("groundXform"); // Give it a name (optional) + groundXform["material"] = groundMaterial; // Apply glass material + groundXform.parentTo(world); // Add to scene + + auto ground = scene.createNode("disk"); // Flat circular disk + ground["radius"] = 10.0; // Large radius (10 units) + ground.parentTo(groundXform); // Put ground in its position controller + + // ======================================================================== + // 🎥 Step 6: Setup Rendering (what/where to save) + // ======================================================================== + auto beautyPass = scene.createNode("beautyPass"); // Defines what to render + beautyPass["saveImage"] = true; // Save the image to disk + beautyPass["outputName"] = "poomer-bella-basic-renderer"; // Filename (will be my_render.png) + + auto outputImagePath = scene.createNode("outputImagePath"); // Where to save + outputImagePath["dir"] = "."; // Current directory + beautyPass["overridePath"] = outputImagePath; // Connect save location + + settings["beautyPass"] = beautyPass; // Tell scene to use this render setup + + // ======================================================================== + // 📱 Step 7: Connect Our Observer + Position Camera + // ======================================================================== + MyEngineObserver observer; // Create our notification listener + engine.subscribe(&observer); // Connect it to the engine + + // Position camera to look at the scene (like framing a photo) + dl::bella_sdk::zoomExtents( + scene.cameraPath(), // Camera's position controller (not camera itself!) + dl::Vec3{ 0,0,0 }, // Look at the origin (center of sphere) + 3.0 // Distance from center + ); + + // Tilt camera down 75 degrees (like looking down from above) + dl::bella_sdk::orbitCamera(scene.cameraPath(), dl::Vec2{ 0.0, -75.0 }); + + // ======================================================================== + // 🚀 Step 8: Render! + // ======================================================================== + engine.start(); // Begin rendering + + // Wait for rendering to complete (check every 100ms) + while (engine.rendering()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + engine.stop(); // Clean shutdown + engine.unsubscribe(&observer); // Disconnect our listener + + return 0; // Tell operating system: "Success!" +} \ No newline at end of file diff --git a/jump_right_in.cpp b/jump_right_in.cpp new file mode 100644 index 0000000..e00343d --- /dev/null +++ b/jump_right_in.cpp @@ -0,0 +1,161 @@ +#include "bella_engine_sdk/src/bella_sdk/bella_engine.h" // Core rendering engine +#include "bella_engine_sdk/src/bella_sdk/bella_scene.h" // Scene management +#include "bella_engine_sdk/src/dl_core/dl_logging.h" // Logging utilities +#include // For std::this_thread (C++ standard library) +#include // For timing operations (C++ standard library) + +// ============================================================================ +// 🔍 C++ Concept: Observer Pattern +// This lets us "listen" for events from the rendering engine. +// When something happens (rendering starts, progress updates, etc.), +// our functions get called automatically. +// ============================================================================ + +struct MyEngineObserver : public dl::bella_sdk::EngineObserver { + // 🔔 Called when rendering begins + void onStarted(dl::String pass) override { + dl::logInfo("🚀 Rendering started: %s", pass.buf()); + } + + // 🔔 Called repeatedly as rendering progresses (0.0 to 1.0) + void onProgress(dl::String pass, dl::bella_sdk::Progress progress) override { + dl::logInfo("⏳ Progress: %.1f%% - %s", + progress.progress() * 100.0, progress.toString().buf()); + } + + // 🔔 Called when we get the final rendered image + void onImage(dl::String pass, dl::bella_sdk::Image image) override { + dl::logInfo("🖼️ Got image: %dx%d pixels", image.width(), image.height()); + } + + // 🔔 Called when rendering finishes + void onStopped(dl::String pass) override { + dl::logInfo("✅ Rendering complete: %s", pass.buf()); + } +}; + +// ============================================================================ +// 🎬 Main Function: Building Our 3D Scene +// ============================================================================ +int main() { + // Step 1: Create the rendering engine and scene + dl::bella_sdk::Engine engine; // The renderer itself + dl::bella_sdk::Scene scene = engine.scene(); // Container for all our objects + scene.loadDefs(); // Load built-in object types + + // Get the "world" - this is the root of our scene tree + dl::bella_sdk::Node world = scene.world(); + + // ======================================================================== + // 📷 Step 2: Create the Camera System + // Every camera needs: sensor (film) + lens + positioning + // ======================================================================== + + // Create a digital "film" sensor (30mm x 30mm) + dl::bella_sdk::Node sensor = scene.createNode("sensor"); + sensor["size"] = dl::Vec2::make(30.0, 30.0); + + // Create a simple lens (like a magnifying glass) + auto lens = scene.createNode("thinLens"); // 'auto' = let C++ figure out the type + + // Create camera positioning system + the camera itself + auto cameraXform = scene.createNode("xform"); // Transform = position/rotation + cameraXform.parentTo(world); // Attach to our world + + auto camera = scene.createNode("camera"); // The actual camera + camera["resolution"] = dl::Vec2::make(320, 320); // 320x320 pixel image + camera["lens"] = lens; // Connect our lens + camera["sensor"] = sensor; // Connect our sensor + camera.parentTo(cameraXform); // Put camera in the positioning system + + // Tell the scene to use this camera for rendering + auto settings = scene.settings(); + settings["camera"] = camera; + + // ======================================================================== + // ☀️ Step 3: Add Lighting + // ======================================================================== + auto skyDome = scene.createNode("skyDome"); // Simulates sky lighting + skyDome.parentTo(world); + settings["environment"] = skyDome; // Use this for scene lighting + + // ======================================================================== + // 🎨 Step 4: Create Materials (like paint or metal finishes) + // ======================================================================== + + // Golden metal material for our sphere + auto sphereMaterial = scene.createNode("conductor"); // Metal material + sphereMaterial["reflectance"] = dl::Rgba::make(0.8, 0.6, 0.2, 1.0); // Golden color (R,G,B,Alpha) + sphereMaterial["roughness"] = 26.1; // Slightly rough surface + + // Glass-like material for the ground + auto groundMaterial = scene.createNode("dielectric"); // Glass/plastic material + groundMaterial["roughness"] = dl::Real(41.0); // Rough surface + + // ======================================================================== + // 🏀 Step 5: Create Objects (Sphere + Ground) + // ======================================================================== + + // Golden sphere in the center + auto sphereXform = scene.createNode("xform"); // Position controller for sphere + sphereXform["material"] = sphereMaterial; // Apply golden material + sphereXform.parentTo(world); // Add to scene + + auto sphere = scene.createNode("sphere"); // The actual sphere shape + sphere["radius"] = dl::Real(1.0); // 1 unit radius + sphere.parentTo(sphereXform); // Put sphere in its position controller + + // Large disk as ground plane + auto groundXform = scene.createNode("xform"); // Position controller for ground + groundXform["name"] = dl::String("groundXform"); // Give it a name (optional) + groundXform["material"] = groundMaterial; // Apply glass material + groundXform.parentTo(world); // Add to scene + + auto ground = scene.createNode("disk"); // Flat circular disk + ground["radius"] = 10.0; // Large radius (10 units) + ground.parentTo(groundXform); // Put ground in its position controller + + // ======================================================================== + // 🎥 Step 6: Setup Rendering (what/where to save) + // ======================================================================== + auto beautyPass = scene.createNode("beautyPass"); // Defines what to render + beautyPass["saveImage"] = true; // Save the image to disk + beautyPass["outputName"] = "jump_right_in"; // Filename (will be my_render.png) + + auto outputImagePath = scene.createNode("outputImagePath"); // Where to save + outputImagePath["dir"] = "."; // Current directory + beautyPass["overridePath"] = outputImagePath; // Connect save location + + settings["beautyPass"] = beautyPass; // Tell scene to use this render setup + + // ======================================================================== + // 📱 Step 7: Connect Our Observer + Position Camera + // ======================================================================== + MyEngineObserver observer; // Create our notification listener + engine.subscribe(&observer); // Connect it to the engine + + // Position camera to look at the scene (like framing a photo) + dl::bella_sdk::zoomExtents( + scene.cameraPath(), // Camera's position controller (not camera itself!) + dl::Vec3{ 0,0,0 }, // Look at the origin (center of sphere) + 3.0 // Distance from center + ); + + // Tilt camera down 75 degrees (like looking down from above) + dl::bella_sdk::orbitCamera(scene.cameraPath(), dl::Vec2{ 0.0, -75.0 }); + + // ======================================================================== + // 🚀 Step 8: Render! + // ======================================================================== + engine.start(); // Begin rendering + + // Wait for rendering to complete (check every 100ms) + while (engine.rendering()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + engine.stop(); // Clean shutdown + engine.unsubscribe(&observer); // Disconnect our listener + + return 0; // Tell operating system: "Success!" +} \ No newline at end of file