From 7339561e5b9e02bbe5c0959e387285f6b2598015 Mon Sep 17 00:00:00 2001 From: Macoy Madson Date: Sun, 15 Nov 2020 11:59:46 -0800 Subject: [PATCH] Got SDL working; Ogre doesn't use its window yet * Moved shared macros into new Macros.cake --- BuildDependencies_Debug.sh | 9 ++++ Build_Debug.sh | 4 +- ReadMe.org | 1 + src/Macros.cake | 71 ++++++++++++++++++++++++++++++ src/OgreCore.cake | 72 ++---------------------------- src/OgreInitialize.cpp | 86 ++++++++++++++++++++++++++++++++++++ src/OgreInitialize.hpp | 1 + src/SDL.cake | 90 ++++++++++++++++++++++++++++++++++++++ test/SDLOgreApp.cake | 49 +++++++++++++++++++++ 9 files changed, 314 insertions(+), 69 deletions(-) create mode 100644 src/Macros.cake create mode 100644 src/SDL.cake create mode 100644 test/SDLOgreApp.cake diff --git a/BuildDependencies_Debug.sh b/BuildDependencies_Debug.sh index 528d4cc..ee1abed 100755 --- a/BuildDependencies_Debug.sh +++ b/BuildDependencies_Debug.sh @@ -4,6 +4,15 @@ echo "Building Cakelisp..." cd Dependencies/cakelisp && jam -j4 && cd ../ echo "done!" +# http://wiki.libsdl.org/Installation +echo "Building SDL" +cd SDL +mkdir -p build +cd build +# mkdir -p SDLBuild +../configure --prefix=$(pwd)SDLBuild && make && make install || exit $? +cd ../ + # See the official script at # https://raw.githubusercontent.com/OGRECave/ogre-next/master/Scripts/BuildScripts/output/build_ogre_linux_c%2B%2Blatest.sh echo "Building Ogre dependencies..." diff --git a/Build_Debug.sh b/Build_Debug.sh index df6802e..25dc21b 100755 --- a/Build_Debug.sh +++ b/Build_Debug.sh @@ -3,4 +3,6 @@ # TODO: Support compiling as a library? # ./Dependencies/cakelisp/bin/cakelisp src/OgreCore.cake || exit $? -./Dependencies/cakelisp/bin/cakelisp --verbose-processes test/OgreApp.cake +# ./Dependencies/cakelisp/bin/cakelisp --verbose-processes test/OgreApp.cake +# ./Dependencies/cakelisp/bin/cakelisp --verbose-processes src/SDL.cake +./Dependencies/cakelisp/bin/cakelisp --verbose-compile-time-build-objects test/SDLOgreApp.cake diff --git a/ReadMe.org b/ReadMe.org index 117bbc5..7ed869b 100644 --- a/ReadMe.org +++ b/ReadMe.org @@ -7,6 +7,7 @@ Clone the repository and its dependencies: #+BEGIN_SRC sh git clone https://macoy.me/code/macoy/gamelib.git git submodule update --init --recursive +hg clone http://hg.libsdl.org/SDL Dependencies/SDL #+END_SRC Build dependencies: diff --git a/src/Macros.cake b/src/Macros.cake new file mode 100644 index 0000000..fef2ab3 --- /dev/null +++ b/src/Macros.cake @@ -0,0 +1,71 @@ +(skip-build) + +(import &comptime-only "../Dependencies/cakelisp/runtime/Macros.cake") + +;; Creates forward declarations in header files. +;; Example usage: +;; (forward-declare (namespace Ogre (class item) (struct my-struct))) +;; Outputs namespace Ogre { class item; struct my-struct;} +(defgenerator forward-declare () + ;; TODO: Support global vs local? + (var is-global bool true) + (var output-dest (& (<> std::vector StringOutput)) + (? is-global (field output header) (field output source))) + + (var end-invocation-index int (FindCloseParenTokenIndex tokens startTokenIndex)) + (var start-body-index int (+ 2 startTokenIndex)) + (var current-index int start-body-index) + (var namespace-stack (<> std::vector int)) + (while (< current-index end-invocation-index) + (var current-token (& (const Token)) (at current-index tokens)) + ;; Invocations + (when (= TokenType_OpenParen (field current-token type)) + (var invocation-token (& (const Token)) (at (+ 1 current-index) tokens)) + (cond + ((= 0 (on-call (field invocation-token contents) compare "namespace")) + (unless (< (+ 3 current-index) end-invocation-index) + (ErrorAtToken invocation-token "missing name or body arguments") + (return false)) + (var namespace-name-token (& (const Token)) (at (+ 2 current-index) tokens)) + (addStringOutput output-dest "namespace" + StringOutMod_SpaceAfter (addr invocation-token)) + (addStringOutput output-dest (field namespace-name-token contents) + StringOutMod_None (addr namespace-name-token)) + (addLangTokenOutput output-dest StringOutMod_OpenBlock (addr namespace-name-token)) + (on-call namespace-stack push_back (FindCloseParenTokenIndex tokens current-index))) + + ((or (= 0 (on-call (field invocation-token contents) compare "class")) + (= 0 (on-call (field invocation-token contents) compare "struct"))) + (unless (< (+ 2 current-index) end-invocation-index) + (ErrorAtToken invocation-token "missing name argument") + (return false)) + (var type-name-token (& (const Token)) (at (+ 2 current-index) tokens)) + (unless (ExpectTokenType "forward-declare" type-name-token TokenType_Symbol) + (return false)) + (addStringOutput output-dest (field invocation-token contents) + StringOutMod_SpaceAfter (addr invocation-token)) + (addStringOutput output-dest (field type-name-token contents) + StringOutMod_None (addr type-name-token)) + (addLangTokenOutput output-dest StringOutMod_EndStatement (addr type-name-token))) + (true + (ErrorAtToken invocation-token "unknown forward-declare type") + (return false)))) + + (when (= TokenType_CloseParen (field current-token type)) + (for-in close-block-index int namespace-stack + (when (= close-block-index current-index) + (addLangTokenOutput output-dest StringOutMod_CloseBlock + (addr (at current-index tokens)))))) + ;; TODO: Support function calls so we can do this recursively? + ;; (set current-index + ;; (getNextArgument tokens current-index end-invocation-index)) + (incr current-index)) + (return true)) + +(defmacro command-add-string-argument () + (destructure-arguments new-argument-index) + (quick-token-at new-argument new-argument-index) + (tokenize-push output (on-call (field linkCommand arguments) push_back + (array ProcessCommandArgumentType_String + (token-splice (addr new-argument))))) + (return true)) diff --git a/src/OgreCore.cake b/src/OgreCore.cake index 226af97..88001ed 100644 --- a/src/OgreCore.cake +++ b/src/OgreCore.cake @@ -1,5 +1,7 @@ (set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src") +(import &comptime-only "Macros.cake") + (c-import "" ;; Ogre dependencies "OgreItem.h" @@ -16,6 +18,8 @@ ;; TODO: convert these functions to cakelisp eventually (defun ogre-initialize (&return bool) (return (OgreInitialize))) +(defun ogre-initialize-sdl (&return bool) + (return (OgreInitializeSDL))) (defun ogre-shutdown () (OgreShutdown)) @@ -94,66 +98,6 @@ (set (field new-scene-node node) scene-node))) (return new-scene-node)) -;; Creates forward declarations in header files. -;; Example usage: -;; (forward-declare (namespace Ogre (class item) (struct my-struct))) -;; Outputs namespace Ogre { class item; struct my-struct;} -(defgenerator forward-declare () - ;; TODO: Support global vs local? - (var is-global bool true) - (var output-dest (& (<> std::vector StringOutput)) - (? is-global (field output header) (field output source))) - - (var end-invocation-index int (FindCloseParenTokenIndex tokens startTokenIndex)) - (var start-body-index int (+ 2 startTokenIndex)) - (var current-index int start-body-index) - (var namespace-stack (<> std::vector int)) - (while (< current-index end-invocation-index) - (var current-token (& (const Token)) (at current-index tokens)) - ;; Invocations - (when (= TokenType_OpenParen (field current-token type)) - (var invocation-token (& (const Token)) (at (+ 1 current-index) tokens)) - (cond - ((= 0 (on-call (field invocation-token contents) compare "namespace")) - (unless (< (+ 3 current-index) end-invocation-index) - (ErrorAtToken invocation-token "missing name or body arguments") - (return false)) - (var namespace-name-token (& (const Token)) (at (+ 2 current-index) tokens)) - (addStringOutput output-dest "namespace" - StringOutMod_SpaceAfter (addr invocation-token)) - (addStringOutput output-dest (field namespace-name-token contents) - StringOutMod_None (addr namespace-name-token)) - (addLangTokenOutput output-dest StringOutMod_OpenBlock (addr namespace-name-token)) - (on-call namespace-stack push_back (FindCloseParenTokenIndex tokens current-index))) - - ((or (= 0 (on-call (field invocation-token contents) compare "class")) - (= 0 (on-call (field invocation-token contents) compare "struct"))) - (unless (< (+ 2 current-index) end-invocation-index) - (ErrorAtToken invocation-token "missing name argument") - (return false)) - (var type-name-token (& (const Token)) (at (+ 2 current-index) tokens)) - (unless (ExpectTokenType "forward-declare" type-name-token TokenType_Symbol) - (return false)) - (addStringOutput output-dest (field invocation-token contents) - StringOutMod_SpaceAfter (addr invocation-token)) - (addStringOutput output-dest (field type-name-token contents) - StringOutMod_None (addr type-name-token)) - (addLangTokenOutput output-dest StringOutMod_EndStatement (addr type-name-token))) - (true - (ErrorAtToken invocation-token "unknown forward-declare type") - (return false)))) - - (when (= TokenType_CloseParen (field current-token type)) - (for-in close-block-index int namespace-stack - (when (= close-block-index current-index) - (addLangTokenOutput output-dest StringOutMod_CloseBlock - (addr (at current-index tokens)))))) - ;; TODO: Support function calls so we can do this recursively? - ;; (set current-index - ;; (getNextArgument tokens current-index end-invocation-index)) - (incr current-index)) - (return true)) - (defun ogre-node-set-position (node (* scene-node) x float y float z float) (on-call-ptr (path node > node) setPosition x y z)) @@ -188,14 +132,6 @@ ;; (return true)) ;; (add-compile-time-hook-module pre-build ogre-pre-build-hook) -(defmacro command-add-string-argument () - (destructure-arguments new-argument-index) - (quick-token-at new-argument new-argument-index) - (tokenize-push output (on-call (field linkCommand arguments) push_back - (array ProcessCommandArgumentType_String - (token-splice (addr new-argument))))) - (return true)) - (defun-comptime ogre-link-hook (manager (& ModuleManager) linkCommand (& ProcessCommand) linkTimeInputs (* ProcessCommandInput) numLinkTimeInputs int diff --git a/src/OgreInitialize.cpp b/src/OgreInitialize.cpp index aeabafa..69951e8 100644 --- a/src/OgreInitialize.cpp +++ b/src/OgreInitialize.cpp @@ -207,6 +207,92 @@ bool OgreInitialize() return true; } +bool OgreInitializeSDL() +{ + using namespace Ogre; + + const String pluginsFolder = "./data/"; + const String writeAccessFolder = "./output/"; + +#ifndef OGRE_STATIC_LIB +#if OGRE_DEBUG_MODE + const char* pluginsFile = "plugins_d.cfg"; +#else + const char* pluginsFile = "plugins.cfg"; +#endif +#endif + g_ogreRoot = OGRE_NEW Root(pluginsFolder + pluginsFile, // + writeAccessFolder + "ogre.cfg", // + writeAccessFolder + "Ogre.log"); + + // This allows the user to configure the graphics. It's damn annoying during dev though + // TODO: Make this return false and quit the app + // if (!g_ogreRoot->showConfigDialog()) + // return false; + + // Initialize Root + RenderSystem* renderSystem = g_ogreRoot->getRenderSystemByName("OpenGL 3+ Rendering Subsystem"); + if (!renderSystem) + { + printf("Render system not found!\n"); + return false; + } + + // renderSystem->setConfigOption("Display Frequency", "N/A"); + renderSystem->setConfigOption("Full Screen", "No"); + // renderSystem->setConfigOption("VSync", "Yes"); + renderSystem->setConfigOption("Video Mode", "1920 x 1080"); + renderSystem->setConfigOption("sRGB Gamma Conversion", "Yes"); + g_ogreRoot->setRenderSystem(renderSystem); + g_window = g_ogreRoot->initialise(/*autoCreateWindow=*/false, "GameLib"); + + // Use the already existing window + // See http://wiki.ogre3d.org/Using+SDL+Input + { + Ogre::NameValuePairList windowSettings; + windowSettings["currentGLContext"] = String("True"); + int winWidth = 1920; + int winHeight = 1080; + g_window = + g_ogreRoot->createRenderWindow("GameLib", winWidth, winHeight, false, &windowSettings); + // renderWindow->setVisible(true); + } + + registerHlms(); + + // Create SceneManager + const size_t numThreads = 1u; + g_sceneManager = g_ogreRoot->createSceneManager(ST_GENERIC, numThreads, "SceneManager"); + + // Create & setup camera + Camera* camera = g_sceneManager->createCamera("Main Camera"); + + // Position it at 500 in Z direction + camera->setPosition(Vector3(0, 5, 15)); + // Look back along -Z + camera->lookAt(Vector3(0, 0, 0)); + camera->setNearClipDistance(0.2f); + camera->setFarClipDistance(1000.0f); + camera->setAutoAspectRatio(true); + + // Setup a basic compositor with a blue clear colour + CompositorManager2* compositorManager = g_ogreRoot->getCompositorManager2(); + const String workspaceName("Main Workspace"); + // const IdString definitionNameId = workspaceName; + const ColourValue backgroundColour(0.2f, 0.4f, 0.6f); + compositorManager->createBasicWorkspaceDef(workspaceName, backgroundColour, IdString()); + compositorManager->addWorkspace(g_sceneManager, g_window->getTexture(), camera, workspaceName, + true); + + Ogre::ResourceGroupManager::getSingleton().addResourceLocation("data/Models", "FileSystem", + "Models"); + + Ogre::WindowEventUtilities::addWindowEventListener(g_window, &g_myWindowEventListener); + + g_graphicsIntialized = true; + return true; +} + void OgreShutdown() { Ogre::WindowEventUtilities::removeWindowEventListener(g_window, &g_myWindowEventListener); diff --git a/src/OgreInitialize.hpp b/src/OgreInitialize.hpp index 872c8cb..a7f40e7 100644 --- a/src/OgreInitialize.hpp +++ b/src/OgreInitialize.hpp @@ -1,6 +1,7 @@ #pragma once bool OgreInitialize(); +bool OgreInitializeSDL(); void OgreShutdown(); namespace Ogre diff --git a/src/SDL.cake b/src/SDL.cake new file mode 100644 index 0000000..74980e3 --- /dev/null +++ b/src/SDL.cake @@ -0,0 +1,90 @@ +(set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src") + +(import &comptime-only "Macros.cake") + +(c-import "stdio.h" + "SDL.h" + "SDL_syswm.h") + +(defun-local print-sdl-error () + (printf "SDL_Error: %s\n" (SDL_GetError))) + +(forward-declare (struct SDL_Window)) + +(defun sdl-initialize (window-out (* (* SDL_Window)) &return bool) + (when (< (SDL_Init SDL_INIT_VIDEO) 0) + (print-sdl-error) + (return false)) + + (set (deref window-out) + (SDL_CreateWindow "Gamelib" + SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED 1920 1080 + (bit-or SDL_WINDOW_RESIZABLE SDL_WINDOW_OPENGL))) + (unless (deref window-out) + (print-sdl-error) + (return false)) + ;; Must explicitly create the GL context for Ogre + (unless (SDL_GL_CreateContext (deref window-out)) + (print-sdl-error) + (return false)) + (return true)) + +(defun sdl-shutdown (window (* SDL_Window)) + (SDL_DestroyWindow window) + (SDL_Quit)) + +;; TODO: Automatically promote this if no main is defined. Separate target instead? +(defun sdl-main (&return int) + (printf "Hello, SDL!\n") + (var window (* SDL_Window) nullptr) + (unless (sdl-initialize (addr window)) (return 1)) + + ;; (var window-surface (* SDL_Surface) (SDL_GetWindowSurface window)) + + (var exit-reason (* (const char)) nullptr) + (while (not exit-reason) + (var event SDL_Event) + (while (SDL_PollEvent (addr event)) + (when (= (field event type) SDL_QUIT) + (set exit-reason "Window event"))) + (SDL_UpdateWindowSurface window)) + + (when exit-reason + (printf "Exiting. Reason: %s\n" exit-reason)) + + (sdl-shutdown window) + (return 0)) + +;; +;; Building +;; + +(set-module-option build-time-compiler "/usr/bin/clang++") +;; Include cakelisp source for DynamicLoader.hpp +(set-module-option build-time-compile-arguments + "-Wall" "-Wextra" "-Wno-unused-parameter" + "-g" "-c" 'source-input "-o" 'object-output "-fPIC" + "-IDependencies/SDL/buildSDLBuild/include/SDL2") + +(defun-comptime sdl-link-hook (manager (& ModuleManager) + linkCommand (& ProcessCommand) + linkTimeInputs (* ProcessCommandInput) numLinkTimeInputs int + &return bool) + ;; TODO: Expose this option somehow? + (var is-debug-build bool true) + + (printf "SDL: Adding %s link arguments\n" (? is-debug-build "debug" "release")) + + (if is-debug-build + ;; TODO: Actually add debug build + (block + (command-add-string-argument "-LDependencies/SDL/buildSDLBuild/lib") + (command-add-string-argument "-lSDL2") + (command-add-string-argument "-Wl,-rpath,.:../Dependencies/SDL/buildSDLBuild/lib")) + (block + (command-add-string-argument "-LDependencies/sdl-next/build/Release/lib") + (command-add-string-argument "-lSDL2") + (command-add-string-argument "-Wl,-rpath,.:../Dependencies/SDL/buildSDLBuild/lib"))) + + (return true)) +(add-compile-time-hook pre-link sdl-link-hook) diff --git a/test/SDLOgreApp.cake b/test/SDLOgreApp.cake new file mode 100644 index 0000000..e700cb7 --- /dev/null +++ b/test/SDLOgreApp.cake @@ -0,0 +1,49 @@ +(set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src") + +(import "../src/OgreCore.cake" + "../src/SDL.cake") +(c-import "SDL.h" "SDL_syswm.h") + +(defun main (&return int) + (var window (* SDL_Window) nullptr) + (unless (sdl-initialize (addr window)) + (return 1)) + ;; Ogre uses exceptions for error handling, so we can't gracefully close without getting all that + ;; stuff set up (which I don't really want to do; it belongs in Gamelib) + (ogre-initialize-sdl) + (var monkey-mesh mesh-handle (ogre-load-mesh "Suzanne.mesh")) + (var monkey-node scene-node (ogre-node-from-item monkey-mesh)) + + (var exit-reason (* (const char)) nullptr) + + (var x float 0.f) + (var y float 0.f) + (var z float 0.f) + + ;; Main loop + (while true + (unless (ogre-handle-window-events) + (set exit-reason "Window closed") + (break)) + + (ogre-node-set-position (addr monkey-node) x y z) + (set x (+ x 0.01f)) + + (unless (ogre-render-frame) + (set exit-reason "Failed to render frame") + (break))) + + (ogre-shutdown) + (when exit-reason + (printf "Exit reason: %s\n" exit-reason)) + (return 0)) + +(set-cakelisp-option executable-output "test/ogreSDLApp") + +;; TODO: Somehow inherit this from SDL.cake? +(set-module-option build-time-compiler "/usr/bin/clang++") +;; Include cakelisp source for DynamicLoader.hpp +(set-module-option build-time-compile-arguments + "-Wall" "-Wextra" "-Wno-unused-parameter" + "-g" "-c" 'source-input "-o" 'object-output "-fPIC" + "-IDependencies/SDL/buildSDLBuild/include/SDL2")