GettingStarted.dox 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /**
  2. \page Building Building Urho3D
  3. Urho3D uses cmake (http://www.cmake.org) to build. The build process has two steps:
  4. 1) Run cmake in the root directory with your preferred toolchain specified to generate the build files. Visual Studio 2008/2010 and MinGW have been tested. You can use the batch files provided (cmake_vs2008.bat, cmake_vs2010.bat and cmake_gcc.bat.)
  5. 2) For Visual Studio, open Urho3D.sln and build the configuration(s) you like. For MinGW, execute make (by default, cmake_gcc.bat specifies to make a Release build.)
  6. The build process will also compile models and shaders from the Source_Asset directory into Bin/Data/Models & Bin/Data/Shaders. Shader compilation requires fxc.exe (from the DirectX SDK) to be available through the system PATH. Note that the debug executables of tools will not have the _d postfix, to allow the asset build scripts to work in both debug & release builds.
  7. After the build is complete, the programs can be run from the Bin directory.
  8. To run Urho3D from the Visual Studio debugger, set it as a startup project and enter its relative path and filename into Properties -> Debugging -> Command: ..\\Bin\\Urho3D.exe (release) or ..\\Bin\\Urho3D_d.exe (debug.) Entering -w into Debugging -> Command Arguments is highly recommended. This enables startup in windowed mode: without it running into an exception or breakpoint will be obnoxious as the mouse cursor will most probably be hidden.
  9. To actually make Urho3D.exe do something useful, it must be supplied with the name of the script file it should load and run. See \ref Running "Running Urho3D" for more information, but for a quick test you can try the following arguments: Scripts/TestScene.as -w
  10. Note: some SM2.0 shaders in Urho3D reach exactly the arithmetic instruction count limit. The fxc.exe in newer DirectX SDK's may fail to compile them. At least the February 2010 SDK is known to work.
  11. \page Running Running Urho3D
  12. Urho3D requires Windows XP or newer, DirectX 9.0c, and a display adapter with SM2.0 support. SM3.0 is highly recommended.
  13. The main executable Urho3D.exe in the Bin directory contains all the engine runtime functionality. However, it does not contain any inbuilt logic or application, and therefore must be supplied with the name of the application script file it should run:
  14. Urho3D.exe <scriptfilename> [options]
  15. The scripting language used is AngelScript (http://www.angelcode.com/angelscript); the script files have .as extension and need to be placed under either the Data or CoreData subdirectories so that Urho3D.exe can find them. An application script is required to have the function void Start(), which will be executed before starting the engine main loop. It is this function's responsibility to initialize the application and to hook up to any necessary \ref Events "events", such as the update that happens every frame.
  16. Currently, two example application scripts exist:
  17. \section Running_TestScene TestScene
  18. Rendering, physics and serialization test. To start, run TestScene.bat in the Bin directory, or use the command Urho3D.exe Scripts/TestScene.as
  19. Key and mouse controls:
  20. \verbatim
  21. WSAD Move
  22. Left mouse Create a new physics object
  23. Right mouse Hold and move mouse to rotate view
  24. Space Toggle debug geometry
  25. F5 Save scene
  26. F7 Load scene
  27. 1 to 9 Toggle rendering options
  28. T Toggle profiling display
  29. ~ Toggle AngelScript console
  30. \endverbatim
  31. \section Running_NinjaSnowWar NinjaSnowWar
  32. A third-person action game. To start, run NinjaSnowWar.bat in the Bin directory, or use the command Urho3D.exe Scripts/NinjaSnowWar.as
  33. Key and mouse controls:
  34. \verbatim
  35. WSAD Move
  36. Left mouse Attack
  37. Space Jump
  38. F1 Toggle physics debug geometry
  39. F2 Toggle profiling display
  40. F3 Toggle octree debug geometry
  41. ~ Toggle AngelScript console
  42. \endverbatim
  43. \section Running_Commandline Command line options
  44. Urho3D.exe understands the following command line options:
  45. \verbatim
  46. -x<res> Horizontal resolution
  47. -y<res> Vertical resolution
  48. -m<level> Enable hardware multisampling (*)
  49. -v Enable vertical sync
  50. -w Start in windowed mode
  51. -headless Headless mode. No application window will be created
  52. -forward Use forward rendering (default)
  53. -prepass Use light pre-pass rendering
  54. -deferred Use deferred rendering
  55. -b<length> Mixing buffer length in milliseconds
  56. -r<freq> Mixing frequency in Hz
  57. -nolimit Disable frame limiter
  58. -noshadows Disable rendering of shadows
  59. -nosound Disable sound output
  60. -noip Disable sound mixing interpolation
  61. -8bit Force 8-bit audio output
  62. -mono Force mono audio output
  63. -sm2 Force SM2.0 rendering
  64. \endverbatim
  65. (*) Only forward rendering supports hardware multisampling. In light pre-pass and deferred rendering modes temporal antialiasing will be used instead.
  66. \page Structure Overall structure
  67. Urho3D consists of several static libraries that are independent where possible: for example the Graphics library could be used without the Engine library, if only rendering capabilities were desired.
  68. The libraries are the following:
  69. - Math. Provides vector & quaternion types and geometric shapes used in intersection tests.
  70. - Core. Provides the execution Context, the base class Object for typed objects, object factories, \ref Event "event handling", threading and profiling.
  71. - IO. Provides file system access, stream input/output and logging.
  72. - %Resource. Provides the ResourceCache and the base resource types, including XML documents.
  73. - %Scene. Provides Node and Component classes, from which Urho3D scenes are built.
  74. - %Graphics. Provides application window handling and 3D rendering capabilities.
  75. - %Input. Provides mouse & keyboard input in both polled and event-based mode.
  76. - %Network. Provides low-level client-server networking functionality.
  77. - %Audio. Provides the audio subsystem and playback of .wav & .ogg sounds in either 2D or 3D.
  78. - Physics. Provides physics simulation.
  79. - %Script. Provides scripting support using the AngelScript language.
  80. - %Engine. Instantiates the subsystems from the libraries above, and manages the main loop iteration.
  81. Urho3D.exe uses just the Engine & Script libraries to start up the subsystems and to load the script file specified on the command line; however due to the cmake build process all the libraries above get automatically linked (as Engine library depends on all of them.)
  82. Although Urho3D.exe itself is geared towards running a scripted application, it is also possible to use the engine through C++ only. When the script subsystem initialization is completely skipped, the resulting executable will also be significantly smaller.
  83. The third-party libraries are used for the following functionality:
  84. - AngelScript: scripting language implementation
  85. - ENet: UDP networking
  86. - FreeType: font rendering
  87. - Open Asset Import Library: reading various 3D file formats
  88. - Open Dynamics %Engine: physics simulation implementation
  89. - StanHull: convex hull generation from triangle meshes, used for physics collision shapes
  90. - stb_image: image loading
  91. - stb_vorbis: Ogg Vorbis decoding
  92. - TinyXML: parsing of XML files
  93. \page Conventions Conventions
  94. Urho3D uses the following conventions and principles:
  95. - Left-handed coordinates. Positive X, Y & Z axes point to the right, up, and forward, and positive rotation is clockwise.
  96. - Degrees are used for angles.
  97. - Clockwise vertices define a front face.
  98. - %Audio volume is specified from 0.0 (silence) to 1.0 (full volume)
  99. - Axis aligned bounding boxes are used in all bounding tests, except for raycast into bone collision boxes, and testing whether a Camera is inside a Zone; in those cases oriented bounding boxes are used instead.
  100. - Path names use slash instead of backslash. Paths will be converted internally into the necessary format when calling into the operating system.
  101. - In the script API, properties are used whenever appropriate instead of Set... and Get... functions. If the setter and getter require index parameters, the property will use array-style indexing, and its name will be in plural. For example model->SetMaterial(0, myMaterial) in C++ would become model.materials[0] = myMaterial in script.
  102. - Raw pointers are used whenever possible in the classes' public API. This simplifies exposing functions & classes to script, and is relatively safe, because SharedPtr & WeakPtr use intrusive reference counting.
  103. - No C++ exceptions. Error return values (false / null pointer / dummy reference) are used instead. %Script exceptions are used when there is no other sensible way, such as with out of bounds array access.
  104. - Feeding illegal data to public API functions, such out of range indices or null pointers, should not cause crashes or corruption. Instead errors are logged as appropriate.
  105. - For threading and multi-instance safety, no mutable static data (including singletons) or function-static data is allowed.
  106. - Third party libraries are included as source code into the main engine project. They are however hidden from the public API as completely as possible.
  107. For more details related to the C++ coding style, see also \ref CodingConventions "Coding conventions".
  108. \page ScriptQuickstart Quickstart in script
  109. When Urho3D.exe executes the application script's Start() function, all the engine subsystems are already in place, so any initialization that needs to be done is specific to the application. In the following example, a minimal "Hello World" application with 3D content will be built.
  110. First we need to declare an object handle for the 3D scene we are going to create. This must be outside the Start() function so that the Scene object will remain even when function's the execution ends. Angelscript uses the @ symbol for object handles, which correspond to SharedPtr's on C++ side (ie. they keep alive the object pointed to.)
  111. \code
  112. Scene@ helloScene;
  113. \endcode
  114. Now we can define the Start() function. First of all we create the 3D scene. Note the lack of "new" keyword. Then we branch off to further initialization functions that will be explained below.
  115. Note: Urho3D has modified AngelScript to allow object handle assignment without the @ symbol, if the object in question does not support value assignment. None of the Urho3D reference-counted objects, such as Scene, support value assignment. In unmodified AngelScript the line would have to read "@helloScene = Scene()".
  116. \code
  117. void Start()
  118. {
  119. helloScene = Scene();
  120. CreateObjects();
  121. CreateText();
  122. SubscribeToEvents();
  123. }
  124. \endcode
  125. In CreateObjects(), which we define next, the scene will be filled with some content. The Urho3D scene model is basically a scene graph; the Scene object serves also as the root node.
  126. Three child nodes will be created: one for a 3D model object, one for a directional light, and one for the camera. The scene nodes themselves display nothing in the 3D world; components need to be created into them for the actual visible content. First, however, we need to create an Octree component into the root node. This is used for accelerated visibility queries to check what the camera "sees", and without it nothing would be visible.
  127. Child nodes can be created with or without names; uniqueness of names is not enforced. In this case we opt to not use names, as we do not need to find the nodes later after creation.
  128. As animation is not needed, we use a StaticModel component for the 3D model. Its scene node remains at the origin (default position of each scene node.) The ResourceCache subsystem is used to load the needed Model & Material resources.
  129. The light scene node also remains at the origin. Position does not matter for directional lights, but the node's forward direction is adjusted so that the light will shine down diagonally.
  130. The camera's scene node will be pulled back along the Z-axis to be able to see the object.
  131. Finally we define a fullscreen Viewport into the Renderer subsystem so that the scene can be shown. The viewport needs Scene and Camera object handles. Note the indexing; multiple viewports could be defined (for example to use split screen rendering) if necessary.
  132. \code
  133. void CreateObjects()
  134. {
  135. helloScene.CreateComponent("Octree");
  136. Node@ objectNode = helloScene.CreateChild();
  137. Node@ lightNode = helloScene.CreateChild();
  138. Node@ cameraNode = helloScene.CreateChild();
  139. StaticModel@ object = objectNode.CreateComponent("StaticModel");
  140. object.model = cache.GetResource("Model", "Models/Mushroom.mdl");
  141. object.material = cache.GetResource("Material", "Materials/Mushroom.xml");
  142. Light@ light = lightNode.CreateComponent("Light");
  143. light.lightType = LIGHT_DIRECTIONAL;
  144. lightNode.direction = Vector3(-1, -1, -1);
  145. Camera@ camera = cameraNode.CreateComponent("Camera");
  146. cameraNode.position = Vector3(0, 0.3, -3);
  147. renderer.viewports[0] = Viewport(helloScene, camera);
  148. }
  149. \endcode
  150. Now that the 3D scene is ready, we move on to displaying "Hello World" on the screen with the help of a Text user interface element. In addition to the Data and CoreData directories, the operating system font directory is available for resource loading; we use the Courier system font with point size 30. To display the text, it is centered, and then added as a child of the user interface root element (the UI can be thought of as a 2D scene graph.)
  151. \code
  152. void CreateText()
  153. {
  154. Text@ helloText = Text();
  155. helloText.SetFont(cache.GetResource("Font", "cour.ttf"), 30);
  156. helloText.text = "Hello World from Urho3D";
  157. helloText.color = Color(0, 1, 0);
  158. helloText.horizontalAlignment = HA_CENTER;
  159. helloText.verticalAlignment = VA_CENTER;
  160. ui.rootElement.AddChild(helloText);
  161. }
  162. \endcode
  163. The final step is to subscribe to the frame update event; otherwise the application would just be left running with no possibility to interact with it, until it was forcibly exited with Alt-F4. The frame update event will be sent on each iteration of the main loop. When subscribing, we need to give the name of the event, and the name of the event handler function. We could also require the event to be sent by a specific sender, but in this case that is unnecessary.
  164. \code
  165. void SubscribeToEvents()
  166. {
  167. SubscribeToEvent("Update", "HandleUpdate");
  168. }
  169. \endcode
  170. The event handler function needs to have a specific signature. If event type and parameters are not needed, "void HandleEvent()", or "void HandleEvent(StringHash eventType, VariantMap& eventData)" if they are.
  171. We might want to expand the application later, so we use the latter form. The current frame's delta time is sent in the update event's parameters, and that will be useful when animating the scene. For now the event handler simply checks from the Input subsystem if the ESC key has been pressed; if it is, the Engine subsystem's \ref Engine::Exit() "Exit()" function will be called. This closes the application window and causes Urho3D.exe to exit after the current main loop iteration finishes.
  172. Note that we could also subscribe to the "KeyDown" event sent by the Input subsystem.
  173. \code
  174. void HandleUpdate(StringHash eventType, VariantMap& eventData)
  175. {
  176. float timeStep = eventData["TimeStep"].GetFloat();
  177. if (input.keyPress[KEY_ESC])
  178. engine.Exit();
  179. }
  180. \endcode
  181. To try out the application, save it as HelloWorld.as in the Bin/Data/Scripts directory, then run Urho3D.exe Scripts/HelloWorld.as
  182. \page CppQuickstart Quickstart in C++
  183. This example shows how to create an Urho3D C++ application from the ground up. The actual functionality will be the same as in \ref ScriptQuickstart "Quickstart in script"; it is strongly recommended that you familiarize yourself with it first.
  184. To start with, create a subdirectory "HelloWorld" into the Urho3D root directory, and add the following line to the root directory's CMakeLists.txt file:
  185. \code
  186. add_subdirectory (HelloWorld)
  187. \endcode
  188. Then, create the following CMakeLists.txt file into the HelloWorld directory (mostly copied from CMakeLists.txt of Urho3D.exe):
  189. \code
  190. # Define target name
  191. set (TARGET_NAME HelloWorld)
  192. # Define source files
  193. file (GLOB CPP_FILES *.cpp)
  194. file (GLOB H_FILES *.h)
  195. set (SOURCE_FILES ${CPP_FILES} ${H_FILES})
  196. # Include directories
  197. include_directories (
  198. ../Engine/Core ../Engine/Engine ../Engine/Graphics ../Engine/Input ../Engine/IO ../Engine/Math
  199. ../Engine/Resource ../Engine/Scene ../Engine/UI
  200. )
  201. # Define target & libraries to link
  202. add_executable (${TARGET_NAME} WIN32 ${SOURCE_FILES})
  203. set_target_properties (${TARGET_NAME} PROPERTIES DEBUG_POSTFIX _d)
  204. target_link_libraries (${TARGET_NAME} Core Engine Graphics Input IO Math Resource Scene UI ${DBGHELP_LIB})
  205. finalize_exe ()
  206. \endcode
  207. Before recreating the build files with cmake, create an empty HelloWorld.cpp into the HelloWorld directory. Now you can re-run cmake. If using Visual Studio, the HelloWorld project should now appear in the Urho3D solution, and you can start writing the actual application into HelloWorld.cpp.
  208. To start with, we need the include files for all the engine classes we are going to use, plus Windows.h for the WinMain function:
  209. \code
  210. #include "Camera.h"
  211. #include "Context.h"
  212. #include "CoreEvents.h"
  213. #include "Engine.h"
  214. #include "Font.h"
  215. #include "Input.h"
  216. #include "Light.h"
  217. #include "Material.h"
  218. #include "Model.h"
  219. #include "Octree.h"
  220. #include "ProcessUtils.h"
  221. #include "Renderer.h"
  222. #include "ResourceCache.h"
  223. #include "Scene.h"
  224. #include "StaticModel.h"
  225. #include "Text.h"
  226. #include "UI.h"
  227. #include <Windows.h>
  228. \endcode
  229. To be able to subscribe to events, we need to subclass Object (if we did not use events, we could do everything procedurally, for example directly in WinMain, but that would be somewhat ugly.) We name the class HelloWorld, with functions that match the script version, plus a constructor. Note the shared pointers to the scene that we will create, and to the ResourceCache, which is perhaps the most often used subsystem, and therefore convenient to store here. Also note the OBJECT(className) macro, which inserts code for object type identification:
  230. \code
  231. class HelloWorld : public Object
  232. {
  233. OBJECT(HelloWorld);
  234. public:
  235. HelloWorld(Context* context);
  236. void Start();
  237. void CreateObjects();
  238. void CreateText();
  239. void SubscribeToEvents();
  240. void HandleUpdate(StringHash eventType, VariantMap& eventData);
  241. SharedPtr<Scene> helloScene_;
  242. SharedPtr<ResourceCache> cache_;
  243. };
  244. \endcode
  245. Before the actual HelloWorld implementation, we define WinMain. First, we need to create the Context object, which holds all subsystems and object factories, and keeps track of event senders and receivers. All Object subclasses need to be supplied a pointer to that context. When using an object factory (such as when creating components) that is automatic, but when creating objects manually, the pointer also needs to be passed manually.
  246. With the context at hand, we create the Engine and initialize it. The arguments for the \ref Engine::Initialize() "Initialize()" function are the initial window title, the log file name, and command line parameters, which are parsed using the ParseArguments() helper function.
  247. After this, we instantiate the HelloWorld object, call its Start() function, and run the main loop until Engine tells that we should exit. The shared pointers will take care of deleting the objects in the correct order; the Context will be the last to be destroyed.
  248. \code
  249. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  250. {
  251. SharedPtr<Context> context(new Context());
  252. SharedPtr<Engine> engine(new Engine(context));
  253. engine->Initialize("HelloWorld", "HelloWorld.log", ParseArguments(cmdLine));
  254. SharedPtr<HelloWorld> helloWorld(new HelloWorld(context));
  255. helloWorld->Start();
  256. while (!engine->IsExiting())
  257. engine->RunFrame();
  258. return 0;
  259. }
  260. \endcode
  261. Now we can start implementing HelloWorld. Note the OBJECTTYPESTATIC(className) macro, which creates the static type name and type name hash for object type identification. For each OBJECT macro, a matching OBJECTTYPESTATIC must appear in a .cpp file.
  262. During construction, we store the ResourceCache subsystem pointer for later access:
  263. \code
  264. OBJECTTYPESTATIC(HelloWorld);
  265. HelloWorld::HelloWorld(Context* context) :
  266. Object(context),
  267. cache_(GetSubsystem<ResourceCache>())
  268. {
  269. }
  270. \endcode
  271. In the Start() function the Scene will be created:
  272. \code
  273. void HelloWorld::Start()
  274. {
  275. helloScene_ = new Scene(context_);
  276. CreateObjects();
  277. CreateText();
  278. SubscribeToEvents();
  279. }
  280. \endcode
  281. Like in the script example, CreateObjects() does the actual scene object creation and defines the viewport. Unlike in script, where properties were used to set the component values and scene node transforms, here we must use setter functions instead. Also, whereas strings were used in script to identify the components to create, here it is most convenient to use the template form of \ref Node::CreateComponent() "CreateComponent()":
  282. \code
  283. void HelloWorld::CreateObjects()
  284. {
  285. helloScene_->CreateComponent<Octree>();
  286. Node* objectNode = helloScene_->CreateChild();
  287. Node* lightNode = helloScene_->CreateChild();
  288. Node* cameraNode = helloScene_->CreateChild();
  289. StaticModel* object = objectNode->CreateComponent<StaticModel>();
  290. object->SetModel(cache_->GetResource<Model>("Models/Mushroom.mdl"));
  291. object->SetMaterial(cache_->GetResource<Material>("Materials/Mushroom.xml"));
  292. Light* light = lightNode->CreateComponent<Light>();
  293. light->SetLightType(LIGHT_DIRECTIONAL);
  294. lightNode->SetDirection(Vector3(-1.0f, -1.0f, -1.0f));
  295. Camera* camera = cameraNode->CreateComponent<Camera>();
  296. cameraNode->SetPosition(Vector3(0.0f, 0.3f, -3.0f));
  297. GetSubsystem<Renderer>()->SetViewport(0, Viewport(helloScene_, camera));
  298. }
  299. \endcode
  300. The text overlay creation is next. Again, setters are used throughout:
  301. \code
  302. void HelloWorld::CreateText()
  303. {
  304. SharedPtr<Text> helloText(new Text(context_));
  305. helloText->SetFont(cache_->GetResource<Font>("cour.ttf"), 30);
  306. helloText->SetText("Hello World from Urho3D");
  307. helloText->SetColor(Color(0.0f, 1.0f, 0.0f));
  308. helloText->SetHorizontalAlignment(HA_CENTER);
  309. helloText->SetVerticalAlignment(VA_CENTER);
  310. GetSubsystem<UI>()->GetRootElement()->AddChild(helloText);
  311. }
  312. \endcode
  313. Finally we get to event subscribing and handling. The helper macro HANDLER is used to create pointers to the event handler member functions: it takes the class name followed by the function name. Note also that unlike script, where events and event parameters are identified with strings, in C++ precalculated hash constants are used instead. The frame update event is defined in CoreEvents.h.
  314. \code
  315. void HelloWorld::SubscribeToEvents()
  316. {
  317. SubscribeToEvent(E_UPDATE, HANDLER(HelloWorld, HandleUpdate));
  318. }
  319. \endcode
  320. Unlike in script, in C++ the event handler function must always have the signature "void HandleEvent(StringHash eventType, VariantMap& eventData)". Note that when accessing event parameters, the event's name is used as a namespace to prevent name clashes:
  321. \code
  322. void HelloWorld::HandleUpdate(StringHash eventType, VariantMap& eventData)
  323. {
  324. float timeStep = eventData[Update::P_TIMESTEP].GetFloat();
  325. if (GetSubsystem<Input>()->GetKeyDown(KEY_ESC))
  326. GetSubsystem<Engine>()->Exit();
  327. }
  328. \endcode
  329. Now you should be ready to compile HelloWorld.cpp. The resulting executable will be placed in the Bin directory. It should be substantially smaller than Urho3D.exe, due to leaving out the scripting functionality.
  330. */