guiMaterialPreview.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. // Original header:
  23. // GuiMaterialPreview Control for Material Editor Written by Travis Vroman of Gaslight Studios
  24. // Updated 2-14-09
  25. // Portions based off Constructor viewport code.
  26. #include "console/engineAPI.h"
  27. #include "T3D/guiMaterialPreview.h"
  28. #include "renderInstance/renderPassManager.h"
  29. #include "lighting/lightManager.h"
  30. #include "lighting/lightInfo.h"
  31. #include "core/resourceManager.h"
  32. #include "scene/sceneManager.h"
  33. #include "scene/sceneRenderState.h"
  34. // GuiMaterialPreview
  35. GuiMaterialPreview::GuiMaterialPreview()
  36. : mMouseState(None),
  37. mModel(NULL),
  38. runThread(0),
  39. lastRenderTime(0),
  40. mLastMousePoint(0, 0),
  41. mFakeSun(NULL),
  42. mMaxOrbitDist(5.0f),
  43. mMinOrbitDist(0.0f),
  44. mOrbitDist(5.0f)
  45. {
  46. mActive = true;
  47. mCameraMatrix.identity();
  48. mCameraRot.set( mDegToRad(30.0f), 0, mDegToRad(-30.0f) );
  49. mCameraPos.set(0.0f, 1.75f, 1.25f);
  50. mCameraMatrix.setColumn(3, mCameraPos);
  51. mOrbitPos.set(0.0f, 0.0f, 0.0f);
  52. mTransStep = 0.01f;
  53. mTranMult = 4.0;
  54. mLightTransStep = 0.01f;
  55. mLightTranMult = 4.0;
  56. mOrbitRelPos = Point3F(0,0,0);
  57. // By default don't do dynamic reflection
  58. // updates for this viewport.
  59. mReflectPriority = 0.0f;
  60. mMountedModel = NULL;
  61. mSkinTag = 0;
  62. }
  63. GuiMaterialPreview::~GuiMaterialPreview()
  64. {
  65. SAFE_DELETE(mModel);
  66. SAFE_DELETE(mFakeSun);
  67. }
  68. bool GuiMaterialPreview::onWake()
  69. {
  70. if( !Parent::onWake() )
  71. return false;
  72. if (!mFakeSun)
  73. mFakeSun = LightManager::createLightInfo();
  74. mFakeSun->setColor( LinearColorF( 1.0f, 1.0f, 1.0f ) );
  75. mFakeSun->setAmbient( LinearColorF( 0.5f, 0.5f, 0.5f ) );
  76. mFakeSun->setDirection( VectorF( 0.0f, 0.707f, -0.707f ) );
  77. mFakeSun->setPosition( mFakeSun->getDirection() * -10000.0f );
  78. mFakeSun->setRange( 2000000.0f );
  79. return true;
  80. }
  81. // This function allows the viewport's ambient color to be changed. This is exposed to script below.
  82. void GuiMaterialPreview::setAmbientLightColor( F32 r, F32 g, F32 b )
  83. {
  84. LinearColorF temp(r, g, b);
  85. temp.clamp();
  86. GuiMaterialPreview::mFakeSun->setAmbient( temp );
  87. }
  88. // This function allows the light's color to be changed. This is exposed to script below.
  89. void GuiMaterialPreview::setLightColor( F32 r, F32 g, F32 b )
  90. {
  91. LinearColorF temp(r, g, b);
  92. temp.clamp();
  93. GuiMaterialPreview::mFakeSun->setColor( temp );
  94. }
  95. // This function is for moving the light in the scene. This needs to be adjusted to keep the light
  96. // from getting all out of whack. For now, we'll just rely on the reset function if we need it
  97. // fixed.
  98. void GuiMaterialPreview::setLightTranslate(S32 modifier, F32 xstep, F32 ystep)
  99. {
  100. F32 _lighttransstep = (modifier & SI_SHIFT ? mLightTransStep : (mLightTransStep*mLightTranMult));
  101. Point3F relativeLightDirection = GuiMaterialPreview::mFakeSun->getDirection();
  102. // May be able to get rid of this. For now, it helps to fix the position of the light if i gets messed up.
  103. if (modifier & SI_PRIMARY_CTRL)
  104. {
  105. relativeLightDirection.x += ( xstep * _lighttransstep * -1 );//need to invert this for some reason. Otherwise, it's backwards.
  106. relativeLightDirection.y += ( ystep * _lighttransstep );
  107. GuiMaterialPreview::mFakeSun->setDirection(relativeLightDirection);
  108. }
  109. // Default action taken by mouse wheel clicking.
  110. else
  111. {
  112. relativeLightDirection.x += ( xstep * _lighttransstep * -1 ); //need to invert this for some reason. Otherwise, it's backwards.
  113. relativeLightDirection.z += ( ystep * _lighttransstep );
  114. GuiMaterialPreview::mFakeSun->setDirection(relativeLightDirection);
  115. }
  116. }
  117. // This is for panning the viewport camera.
  118. void GuiMaterialPreview::setTranslate(S32 modifier, F32 xstep, F32 ystep)
  119. {
  120. F32 transstep = (modifier & SI_SHIFT ? mTransStep : (mTransStep*mTranMult));
  121. F32 nominalDistance = 20.0;
  122. Point3F vec = mCameraPos;
  123. vec -= mOrbitPos;
  124. transstep *= vec.len() / nominalDistance;
  125. if (modifier & SI_PRIMARY_CTRL)
  126. {
  127. mOrbitRelPos.x += ( xstep * transstep );
  128. mOrbitRelPos.y += ( ystep * transstep );
  129. }
  130. else
  131. {
  132. mOrbitRelPos.x += ( xstep * transstep );
  133. mOrbitRelPos.z += ( ystep * transstep );
  134. }
  135. }
  136. // Left Click
  137. void GuiMaterialPreview::onMouseDown(const GuiEvent &event)
  138. {
  139. mMouseState = MovingLight;
  140. mLastMousePoint = event.mousePoint;
  141. mouseLock();
  142. }
  143. // Left Click Release
  144. void GuiMaterialPreview::onMouseUp(const GuiEvent &event)
  145. {
  146. mouseUnlock();
  147. mMouseState = None;
  148. }
  149. // Left Click Drag
  150. void GuiMaterialPreview::onMouseDragged(const GuiEvent &event)
  151. {
  152. if(mMouseState != MovingLight)
  153. {
  154. return;
  155. }
  156. // If we are MovingLight...
  157. else
  158. {
  159. Point2I delta = event.mousePoint - mLastMousePoint;
  160. mLastMousePoint = event.mousePoint;
  161. setLightTranslate(event.modifier, delta.x, delta.y);
  162. }
  163. }
  164. // Right Click
  165. void GuiMaterialPreview::onRightMouseDown(const GuiEvent &event)
  166. {
  167. mMouseState = Rotating;
  168. mLastMousePoint = event.mousePoint;
  169. mouseLock();
  170. }
  171. // Right Click Release
  172. void GuiMaterialPreview::onRightMouseUp(const GuiEvent &event)
  173. {
  174. mouseUnlock();
  175. mMouseState = None;
  176. }
  177. // Right Click Drag
  178. void GuiMaterialPreview::onRightMouseDragged(const GuiEvent &event)
  179. {
  180. if (mMouseState != Rotating)
  181. {
  182. return;
  183. }
  184. Point2I delta = event.mousePoint - mLastMousePoint;
  185. mLastMousePoint = event.mousePoint;
  186. mCameraRot.x += (delta.y * 0.01f);
  187. mCameraRot.z += (delta.x * 0.01f);
  188. }
  189. // Mouse Wheel Scroll Up
  190. bool GuiMaterialPreview::onMouseWheelUp(const GuiEvent &event)
  191. {
  192. mOrbitDist = (mOrbitDist - 0.10f);
  193. return true;
  194. }
  195. // Mouse Wheel Scroll Down
  196. bool GuiMaterialPreview::onMouseWheelDown(const GuiEvent &event)
  197. {
  198. mOrbitDist = (mOrbitDist + 0.10f);
  199. return true;
  200. }
  201. // Mouse Wheel Click
  202. void GuiMaterialPreview::onMiddleMouseDown(const GuiEvent &event)
  203. {
  204. if (!mActive || !mVisible || !mAwake)
  205. {
  206. return;
  207. }
  208. mMouseState = Panning;
  209. mLastMousePoint = event.mousePoint;
  210. mouseLock();
  211. }
  212. // Mouse Wheel Click Release
  213. void GuiMaterialPreview::onMiddleMouseUp(const GuiEvent &event)
  214. {
  215. mouseUnlock();
  216. mMouseState = None;
  217. }
  218. // Mouse Wheel Click Drag
  219. void GuiMaterialPreview::onMiddleMouseDragged(const GuiEvent &event)
  220. {
  221. if (mMouseState != Panning)
  222. {
  223. return;
  224. }
  225. Point2I delta = event.mousePoint - mLastMousePoint;
  226. mLastMousePoint = event.mousePoint;
  227. setTranslate(event.modifier, delta.x, delta.y);
  228. }
  229. // This is used to set the model we want to view in the control object.
  230. void GuiMaterialPreview::setObjectModel(const char* modelName)
  231. {
  232. deleteModel();
  233. Resource<TSShape> model = ResourceManager::get().load(modelName);
  234. if (! bool(model))
  235. {
  236. Con::warnf(avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
  237. return;
  238. }
  239. mModel = new TSShapeInstance(model, true);
  240. AssertFatal(mModel, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
  241. // Initialize camera values:
  242. mOrbitPos = mModel->getShape()->center;
  243. mMinOrbitDist = mModel->getShape()->mRadius;
  244. lastRenderTime = Platform::getVirtualMilliseconds();
  245. }
  246. void GuiMaterialPreview::deleteModel()
  247. {
  248. SAFE_DELETE(mModel);
  249. runThread = 0;
  250. }
  251. // This is called whenever there is a change in the camera.
  252. bool GuiMaterialPreview::processCameraQuery(CameraQuery* query)
  253. {
  254. MatrixF xRot, zRot;
  255. Point3F vecf, vecu, vecr;;
  256. xRot.set(EulerF(mCameraRot.x, 0.0f, 0.0f));
  257. zRot.set(EulerF(0.0f, 0.0f, mCameraRot.z));
  258. if(mMouseState != Panning)
  259. {
  260. // Adjust the camera so that we are still facing the model:
  261. Point3F vec;
  262. mCameraMatrix.mul(zRot, xRot);
  263. mCameraMatrix.getColumn(1, &vec);
  264. vec *= mOrbitDist;
  265. mCameraPos = mOrbitPos - vec;
  266. query->farPlane = 2100.0f;
  267. query->nearPlane = query->farPlane / 5000.0f;
  268. query->fov = 45.0f;
  269. mCameraMatrix.setColumn(3, mCameraPos);
  270. query->cameraMatrix = mCameraMatrix;
  271. }
  272. else
  273. {
  274. mCameraMatrix.mul( zRot, xRot );
  275. mCameraMatrix.getColumn( 1, &vecf ); // Forward vector
  276. mCameraMatrix.getColumn( 2, &vecu ); // Up vector
  277. mCameraMatrix.getColumn( 0, &vecr ); // Right vector
  278. Point3F flatVecf(vecf.x, vecf.y, 0.0f);
  279. Point3F modvecf = flatVecf * mOrbitRelPos.y;
  280. Point3F modvecu = vecu * mOrbitRelPos.z;
  281. Point3F modvecr = vecr * mOrbitRelPos.x;
  282. // Change the orbit position
  283. mOrbitPos += modvecu - modvecr + modvecf;
  284. F32 vecfmul = mOrbitDist;
  285. Point3F virtualVecF = vecf * mOrbitDist;
  286. vecf *= vecfmul;
  287. mCameraPos = mOrbitPos - virtualVecF;
  288. // Update the camera's position
  289. mCameraMatrix.setColumn( 3, (mOrbitPos - vecf) );
  290. query->farPlane = 2100.0f;
  291. query->nearPlane = query->farPlane / 5000.0f;
  292. query->fov = 45.0f;
  293. query->cameraMatrix = mCameraMatrix;
  294. // Reset the relative position
  295. mOrbitRelPos = Point3F(0,0,0);
  296. }
  297. return true;
  298. }
  299. void GuiMaterialPreview::onMouseEnter(const GuiEvent & event)
  300. {
  301. Con::executef(this, "onMouseEnter");
  302. }
  303. void GuiMaterialPreview::onMouseLeave(const GuiEvent & event)
  304. {
  305. Con::executef(this, "onMouseLeave");
  306. }
  307. void GuiMaterialPreview::renderWorld(const RectI &updateRect)
  308. {
  309. // nothing to render, punt
  310. if ( !mModel && !mMountedModel )
  311. return;
  312. S32 time = Platform::getVirtualMilliseconds();
  313. //S32 dt = time - lastRenderTime;
  314. lastRenderTime = time;
  315. F32 left, right, top, bottom, nearPlane, farPlane;
  316. bool isOrtho;
  317. GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho);
  318. Frustum frust( isOrtho, left, right, bottom, top, nearPlane, farPlane, MatrixF::Identity );
  319. FogData savedFogData = gClientSceneGraph->getFogData();
  320. gClientSceneGraph->setFogData( FogData() ); // no fog in preview window
  321. RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass();
  322. SceneRenderState state
  323. (
  324. gClientSceneGraph,
  325. SPT_Diffuse,
  326. SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ),
  327. renderPass,
  328. true
  329. );
  330. // Set up our TS render state here.
  331. TSRenderState rdata;
  332. rdata.setSceneState( &state );
  333. // We might have some forward lit materials
  334. // so pass down a query to gather lights.
  335. LightQuery query;
  336. query.init( SphereF( Point3F::Zero, 1.0f ) );
  337. rdata.setLightQuery( &query );
  338. // Set up pass transforms
  339. renderPass->assignSharedXform(RenderPassManager::View, MatrixF::Identity);
  340. renderPass->assignSharedXform(RenderPassManager::Projection, GFX->getProjectionMatrix());
  341. LIGHTMGR->unregisterAllLights();
  342. LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun );
  343. if ( mModel )
  344. mModel->render( rdata );
  345. if ( mMountedModel )
  346. {
  347. // render a weapon
  348. /*
  349. MatrixF mat;
  350. GFX->pushWorldMatrix();
  351. GFX->multWorld( mat );
  352. GFX->popWorldMatrix();
  353. */
  354. }
  355. renderPass->renderPass( &state );
  356. gClientSceneGraph->setFogData( savedFogData ); // restore fog setting
  357. // Make sure to remove our fake sun
  358. LIGHTMGR->unregisterAllLights();
  359. }
  360. // Make sure the orbit distance is within the acceptable range.
  361. void GuiMaterialPreview::setOrbitDistance(F32 distance)
  362. {
  363. mOrbitDist = mClampF(distance, mMinOrbitDist, mMaxOrbitDist);
  364. }
  365. // This function is meant to be used with a button to put everything back to default settings.
  366. void GuiMaterialPreview::resetViewport()
  367. {
  368. // Reset the camera's orientation.
  369. mCameraRot.set( mDegToRad(30.0f), 0, mDegToRad(-30.0f) );
  370. mCameraPos.set(0.0f, 1.75f, 1.25f);
  371. mOrbitDist = 5.0f;
  372. mOrbitPos = mModel->getShape()->center;
  373. // Reset the viewport's lighting.
  374. GuiMaterialPreview::mFakeSun->setColor( LinearColorF( 1.0f, 1.0f, 1.0f ) );
  375. GuiMaterialPreview::mFakeSun->setAmbient( LinearColorF( 0.5f, 0.5f, 0.5f ) );
  376. GuiMaterialPreview::mFakeSun->setDirection( VectorF( 0.0f, 0.707f, -0.707f ) );
  377. }
  378. // Expose the class and functions to the console.
  379. IMPLEMENT_CONOBJECT(GuiMaterialPreview);
  380. ConsoleDocClass( GuiMaterialPreview,
  381. "@brief Visual preview of a specified Material\n\n"
  382. "Editor use only.\n\n"
  383. "@internal"
  384. );
  385. // Set the model.
  386. DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* shapeName ),,
  387. "Sets the model to be displayed in this control\n\n"
  388. "@param shapeName Name of the model to display.\n")
  389. {
  390. object->setObjectModel(shapeName);
  391. }
  392. DefineEngineMethod(GuiMaterialPreview, deleteModel, void, (),,
  393. "Deletes the preview model.\n")
  394. {
  395. object->deleteModel();
  396. }
  397. // Set orbit distance around the model.
  398. DefineEngineMethod(GuiMaterialPreview, setOrbitDistance, void, ( F32 distance ),,
  399. "Sets the distance at which the camera orbits the object. Clamped to the "
  400. "acceptable range defined in the class by min and max orbit distances.\n\n"
  401. "@param distance The distance to set the orbit to (will be clamped).")
  402. {
  403. object->setOrbitDistance(distance);
  404. }
  405. // Reset control to default values. Meant to be used with a button.
  406. DefineEngineMethod(GuiMaterialPreview, reset, void, (),,
  407. "Resets the viewport to default zoom, pan, rotate and lighting.")
  408. {
  409. object->resetViewport();
  410. }
  411. // This function allows the user to change the light's color.
  412. DefineEngineMethod(GuiMaterialPreview, setLightColor, void, ( LinearColorF color ),,
  413. "Sets the color of the light in the scene.\n")
  414. {
  415. object->setLightColor( color.red, color.green, color.blue );
  416. }
  417. // This function allows the user to change the viewports's ambient color.
  418. DefineEngineMethod(GuiMaterialPreview, setAmbientLightColor, void, ( LinearColorF color ),,
  419. "Sets the color of the ambient light in the scene.\n")
  420. {
  421. object->setAmbientLightColor( color.red, color.green, color.blue );
  422. }