Main.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Framework includes
  2. #include "BsApplication.h"
  3. #include "Resources/BsResources.h"
  4. #include "Resources/BsBuiltinResources.h"
  5. #include "Material/BsMaterial.h"
  6. #include "Components/BsCCamera.h"
  7. #include "Components/BsCRenderable.h"
  8. #include "Components/BsCAnimation.h"
  9. #include "Components/BsCSkybox.h"
  10. #include "RenderAPI/BsRenderAPI.h"
  11. #include "RenderAPI/BsRenderWindow.h"
  12. #include "Scene/BsSceneObject.h"
  13. // Example includes
  14. #include "BsCameraFlyer.h"
  15. #include "BsExampleFramework.h"
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // This example demonstrates how to animate a 3D model using skeletal animation. Aside from animation this example is
  18. // structurally similar to PhysicallyBasedShading example.
  19. //
  20. // The example first loads necessary resources, including a mesh and textures to use for rendering, as well as an animation
  21. // clip. The animation clip is imported from the same file as the 3D model. Special import options are used to tell the
  22. // importer to import data required for skeletal animation. It then proceeds to register the relevant keys used for
  23. // controling the camera. Next it sets up the 3D scene using the mesh, textures, material and adds an animation
  24. // component. The animation component start playing the animation clip we imported earlier. Finally it sets up a camera,
  25. // along with CameraFlyer component that allows the user to fly around the scene.
  26. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  27. namespace bs
  28. {
  29. UINT32 windowResWidth = 1280;
  30. UINT32 windowResHeight = 720;
  31. /** Container for all resources used by the example. */
  32. struct Assets
  33. {
  34. HMesh exampleModel;
  35. HAnimationClip exampleAnimClip;
  36. HTexture exampleAlbedoTex;
  37. HTexture exampleNormalsTex;
  38. HTexture exampleRoughnessTex;
  39. HTexture exampleMetalnessTex;
  40. HTexture exampleSkyCubemap;
  41. HMaterial exampleMaterial;
  42. };
  43. /** Load the resources we'll be using throughout the example. */
  44. Assets loadAssets()
  45. {
  46. Assets assets;
  47. // Load the 3D model and the animation clip
  48. // Set up a path to the model resource
  49. const Path exampleDataPath = EXAMPLE_DATA_PATH;
  50. const Path modelPath = exampleDataPath + "MechDrone/Drone.FBX";
  51. // Set up mesh import options so that we import information about the skeleton and the skin, as well as any
  52. // animation clips the model might have.
  53. SPtr<MeshImportOptions> meshImportOptions = MeshImportOptions::create();
  54. meshImportOptions->setImportSkin(true);
  55. meshImportOptions->setImportAnimation(true);
  56. // The FBX file contains multiple resources (a mesh and an animation clip), therefore we use importAll() method,
  57. // which imports all resources in a file.
  58. Vector<SubResource> modelResources = gImporter().importAll(modelPath, meshImportOptions);
  59. for(auto& entry : modelResources)
  60. {
  61. if(rtti_is_of_type<Mesh>(entry.value.get()))
  62. assets.exampleModel = static_resource_cast<Mesh>(entry.value);
  63. else if(rtti_is_of_type<AnimationClip>(entry.value.get()))
  64. assets.exampleAnimClip = static_resource_cast<AnimationClip>(entry.value);
  65. }
  66. // Load PBR textures for the 3D model
  67. assets.exampleAlbedoTex = ExampleFramework::loadTexture(ExampleTexture::DroneAlbedo);
  68. assets.exampleNormalsTex = ExampleFramework::loadTexture(ExampleTexture::DroneNormal, false);
  69. assets.exampleRoughnessTex = ExampleFramework::loadTexture(ExampleTexture::DroneRoughness, false);
  70. assets.exampleMetalnessTex = ExampleFramework::loadTexture(ExampleTexture::DroneMetalness, false);
  71. // Create a material using the default physically based shader, and apply the PBR textures we just loaded
  72. HShader shader = gBuiltinResources().getBuiltinShader(BuiltinShader::Standard);
  73. assets.exampleMaterial = Material::create(shader);
  74. assets.exampleMaterial->setTexture("gAlbedoTex", assets.exampleAlbedoTex);
  75. assets.exampleMaterial->setTexture("gNormalTex", assets.exampleNormalsTex);
  76. assets.exampleMaterial->setTexture("gRoughnessTex", assets.exampleRoughnessTex);
  77. assets.exampleMaterial->setTexture("gMetalnessTex", assets.exampleMetalnessTex);
  78. // Load an environment map
  79. assets.exampleSkyCubemap = ExampleFramework::loadTexture(ExampleTexture::EnvironmentRathaus, false, true, true);
  80. return assets;
  81. }
  82. /** Set up the 3D object used by the example, and the camera to view the world through. */
  83. void setUp3DScene(const Assets& assets)
  84. {
  85. /************************************************************************/
  86. /* RENDERABLE */
  87. /************************************************************************/
  88. // Now we create a scene object that has a position, orientation, scale and optionally components to govern its
  89. // logic. In this particular case we are creating a SceneObject with a Renderable component which will render a
  90. // mesh at the position of the scene object with the provided material.
  91. // Create new scene object at (0, 0, 0)
  92. HSceneObject droneSO = SceneObject::create("Drone");
  93. // Attach the Renderable component and hook up the mesh we loaded, and the material we created.
  94. HRenderable renderable = droneSO->addComponent<CRenderable>();
  95. renderable->setMesh(assets.exampleModel);
  96. renderable->setMaterial(assets.exampleMaterial);
  97. /************************************************************************/
  98. /* ANIMATION */
  99. /************************************************************************/
  100. // Add an animation component to the same scene object we added Renderable to.
  101. HAnimation animation = droneSO->addComponent<CAnimation>();
  102. // Start playing the animation clip we imported
  103. animation->play(assets.exampleAnimClip);
  104. /************************************************************************/
  105. /* SKYBOX */
  106. /************************************************************************/
  107. // Add a skybox texture for sky reflections
  108. HSceneObject skyboxSO = SceneObject::create("Skybox");
  109. HSkybox skybox = skyboxSO->addComponent<CSkybox>();
  110. skybox->setTexture(assets.exampleSkyCubemap);
  111. /************************************************************************/
  112. /* CAMERA */
  113. /************************************************************************/
  114. // In order something to render on screen we need at least one camera.
  115. // Like before, we create a new scene object at (0, 0, 0).
  116. HSceneObject sceneCameraSO = SceneObject::create("SceneCamera");
  117. // Get the primary render window we need for creating the camera.
  118. SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
  119. // Add a Camera component that will output whatever it sees into that window
  120. // (You could also use a render texture or another window you created).
  121. HCamera sceneCamera = sceneCameraSO->addComponent<CCamera>();
  122. sceneCamera->getViewport()->setTarget(window);
  123. // Set up camera component properties
  124. // Set closest distance that is visible. Anything below that is clipped.
  125. sceneCamera->setNearClipDistance(0.005f);
  126. // Set farthest distance that is visible. Anything above that is clipped.
  127. sceneCamera->setFarClipDistance(1000);
  128. // Set aspect ratio depending on the current resolution
  129. sceneCamera->setAspectRatio(windowResWidth / (float)windowResHeight);
  130. // Enable indirect lighting so we get accurate diffuse lighting from the skybox environment map
  131. const SPtr<RenderSettings>& renderSettings = sceneCamera->getRenderSettings();
  132. renderSettings->enableIndirectLighting = true;
  133. sceneCamera->setRenderSettings(renderSettings);
  134. // Add a CameraFlyer component that allows us to move the camera. See CameraFlyer for more information.
  135. sceneCameraSO->addComponent<CameraFlyer>();
  136. // Position and orient the camera scene object
  137. sceneCameraSO->setPosition(Vector3(0.0f, 2.5f, -4.0f) * 0.65f);
  138. sceneCameraSO->lookAt(Vector3(0, 1.5f, 0));
  139. }
  140. }
  141. /** Main entry point into the application. */
  142. #if BS_PLATFORM == BS_PLATFORM_WIN32
  143. #include <windows.h>
  144. int CALLBACK WinMain(
  145. _In_ HINSTANCE hInstance,
  146. _In_ HINSTANCE hPrevInstance,
  147. _In_ LPSTR lpCmdLine,
  148. _In_ int nCmdShow
  149. )
  150. #else
  151. int main()
  152. #endif
  153. {
  154. using namespace bs;
  155. // Initializes the application and creates a window with the specified properties
  156. VideoMode videoMode(windowResWidth, windowResHeight);
  157. Application::startUp(videoMode, "Example", false);
  158. // Registers a default set of input controls
  159. ExampleFramework::setupInputConfig();
  160. // Load a model and textures, create materials
  161. Assets assets = loadAssets();
  162. // Set up the scene with an object to render and a camera
  163. setUp3DScene(assets);
  164. // Runs the main loop that does most of the work. This method will exit when user closes the main
  165. // window or exits in some other way.
  166. Application::instance().runMainLoop();
  167. // When done, clean up
  168. Application::shutDown();
  169. return 0;
  170. }