RenderManager.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /*
  2. * Copyright (c) 2009-2010 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.renderer;
  33. import com.jme3.material.Material;
  34. import com.jme3.material.RenderState;
  35. import com.jme3.math.Matrix3f;
  36. import com.jme3.math.Matrix4f;
  37. import com.jme3.math.Quaternion;
  38. import com.jme3.math.Vector2f;
  39. import com.jme3.math.Vector3f;
  40. import com.jme3.post.SceneProcessor;
  41. import com.jme3.renderer.queue.GeometryList;
  42. import com.jme3.renderer.queue.RenderQueue;
  43. import com.jme3.renderer.queue.RenderQueue.Bucket;
  44. import com.jme3.scene.Geometry;
  45. import com.jme3.scene.Mesh;
  46. import com.jme3.scene.Node;
  47. import com.jme3.scene.Spatial;
  48. import com.jme3.scene.VertexBuffer;
  49. import com.jme3.shader.Uniform;
  50. import com.jme3.shader.VarType;
  51. import com.jme3.system.NullRenderer;
  52. import com.jme3.system.Timer;
  53. import com.jme3.util.IntMap.Entry;
  54. import com.jme3.util.TempVars;
  55. import java.util.ArrayList;
  56. import java.util.Collections;
  57. import java.util.List;
  58. import java.util.logging.Logger;
  59. /**
  60. * <code>RenderManager</code> is a high-level rendering interface that is
  61. * above the Renderer implementation. RenderManager takes care
  62. * of rendering the scene graphs attached to each viewport and
  63. * handling SceneProcessors.
  64. *
  65. * @see SceneProcessor
  66. * @see ViewPort
  67. * @see Spatial
  68. */
  69. public class RenderManager {
  70. private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
  71. private Renderer renderer;
  72. private Timer timer;
  73. private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>();
  74. private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
  75. private ArrayList<ViewPort> postViewPorts = new ArrayList<ViewPort>();
  76. private Camera prevCam = null;
  77. private Material forcedMaterial = null;
  78. private String forcedTechnique = null;
  79. private RenderState forcedRenderState = null;
  80. private boolean shader;
  81. private int viewX, viewY, viewWidth, viewHeight;
  82. private float near, far;
  83. private Matrix4f orthoMatrix = new Matrix4f();
  84. private Matrix4f viewMatrix = new Matrix4f();
  85. private Matrix4f projMatrix = new Matrix4f();
  86. private Matrix4f viewProjMatrix = new Matrix4f();
  87. private Matrix4f worldMatrix = new Matrix4f();
  88. private Vector3f camUp = new Vector3f(),
  89. camLeft = new Vector3f(),
  90. camDir = new Vector3f(),
  91. camLoc = new Vector3f();
  92. //temp technique
  93. private String tmpTech;
  94. /**
  95. * Create a high-level rendering interface over the
  96. * low-level rendering interface.
  97. * @param renderer
  98. */
  99. public RenderManager(Renderer renderer) {
  100. this.renderer = renderer;
  101. //this.shader = renderer.getCaps().contains(Caps.GLSL100);
  102. }
  103. public ViewPort getPreView(String viewName) {
  104. for (int i = 0; i < preViewPorts.size(); i++) {
  105. if (preViewPorts.get(i).getName().equals(viewName)) {
  106. return preViewPorts.get(i);
  107. }
  108. }
  109. return null;
  110. }
  111. public boolean removePreView(ViewPort view) {
  112. return preViewPorts.remove(view);
  113. }
  114. public ViewPort getMainView(String viewName) {
  115. for (int i = 0; i < viewPorts.size(); i++) {
  116. if (viewPorts.get(i).getName().equals(viewName)) {
  117. return viewPorts.get(i);
  118. }
  119. }
  120. return null;
  121. }
  122. public boolean removeMainView(String viewName) {
  123. for (int i = 0; i < viewPorts.size(); i++) {
  124. if (viewPorts.get(i).getName().equals(viewName)) {
  125. viewPorts.remove(i);
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. public boolean removeMainView(ViewPort view) {
  132. return viewPorts.remove(view);
  133. }
  134. public ViewPort getPostView(String viewName) {
  135. for (int i = 0; i < postViewPorts.size(); i++) {
  136. if (postViewPorts.get(i).getName().equals(viewName)) {
  137. return postViewPorts.get(i);
  138. }
  139. }
  140. return null;
  141. }
  142. public boolean removePostView(String viewName) {
  143. for (int i = 0; i < postViewPorts.size(); i++) {
  144. if (postViewPorts.get(i).getName().equals(viewName)) {
  145. postViewPorts.remove(i);
  146. return true;
  147. }
  148. }
  149. return false;
  150. }
  151. public boolean removePostView(ViewPort view) {
  152. return postViewPorts.remove(view);
  153. }
  154. public List<ViewPort> getPreViews() {
  155. return Collections.unmodifiableList(preViewPorts);
  156. }
  157. public List<ViewPort> getMainViews() {
  158. return Collections.unmodifiableList(viewPorts);
  159. }
  160. public List<ViewPort> getPostViews() {
  161. return Collections.unmodifiableList(postViewPorts);
  162. }
  163. /**
  164. * Creates a new viewport, to display the given camera's content.
  165. * The view will be processed before the primary viewport.
  166. * @param viewName
  167. * @param cam
  168. * @return
  169. */
  170. public ViewPort createPreView(String viewName, Camera cam) {
  171. ViewPort vp = new ViewPort(viewName, cam);
  172. preViewPorts.add(vp);
  173. return vp;
  174. }
  175. public ViewPort createMainView(String viewName, Camera cam) {
  176. ViewPort vp = new ViewPort(viewName, cam);
  177. viewPorts.add(vp);
  178. return vp;
  179. }
  180. public ViewPort createPostView(String viewName, Camera cam) {
  181. ViewPort vp = new ViewPort(viewName, cam);
  182. postViewPorts.add(vp);
  183. return vp;
  184. }
  185. private void notifyReshape(ViewPort vp, int w, int h) {
  186. List<SceneProcessor> processors = vp.getProcessors();
  187. for (SceneProcessor proc : processors) {
  188. if (!proc.isInitialized()) {
  189. proc.initialize(this, vp);
  190. } else {
  191. proc.reshape(vp, w, h);
  192. }
  193. }
  194. }
  195. /**
  196. * @param w
  197. * @param h
  198. */
  199. public void notifyReshape(int w, int h) {
  200. for (ViewPort vp : preViewPorts) {
  201. if (vp.getOutputFrameBuffer() == null) {
  202. Camera cam = vp.getCamera();
  203. cam.resize(w, h, true);
  204. }
  205. notifyReshape(vp, w, h);
  206. }
  207. for (ViewPort vp : viewPorts) {
  208. if (vp.getOutputFrameBuffer() == null) {
  209. Camera cam = vp.getCamera();
  210. cam.resize(w, h, true);
  211. }
  212. notifyReshape(vp, w, h);
  213. }
  214. for (ViewPort vp : postViewPorts) {
  215. if (vp.getOutputFrameBuffer() == null) {
  216. Camera cam = vp.getCamera();
  217. cam.resize(w, h, true);
  218. }
  219. notifyReshape(vp, w, h);
  220. }
  221. }
  222. public void updateUniformBindings(List<Uniform> params) {
  223. // assums worldMatrix is properly set.
  224. TempVars vars = TempVars.get();
  225. assert vars.lock();
  226. Matrix4f tempMat4 = vars.tempMat4;
  227. Matrix3f tempMat3 = vars.tempMat3;
  228. Vector2f tempVec2 = vars.vect2d;
  229. Quaternion tempVec4 = vars.quat1;
  230. for (int i = 0; i < params.size(); i++) {
  231. Uniform u = params.get(i);
  232. switch (u.getBinding()) {
  233. case WorldMatrix:
  234. u.setValue(VarType.Matrix4, worldMatrix);
  235. break;
  236. case ViewMatrix:
  237. u.setValue(VarType.Matrix4, viewMatrix);
  238. break;
  239. case ProjectionMatrix:
  240. u.setValue(VarType.Matrix4, projMatrix);
  241. break;
  242. case ViewProjectionMatrix:
  243. u.setValue(VarType.Matrix4, viewProjMatrix);
  244. break;
  245. case WorldViewMatrix:
  246. tempMat4.set(viewMatrix);
  247. tempMat4.multLocal(worldMatrix);
  248. u.setValue(VarType.Matrix4, tempMat4);
  249. break;
  250. case NormalMatrix:
  251. tempMat4.set(viewMatrix);
  252. tempMat4.multLocal(worldMatrix);
  253. tempMat4.toRotationMatrix(tempMat3);
  254. tempMat3.invertLocal();
  255. tempMat3.transposeLocal();
  256. u.setValue(VarType.Matrix3, tempMat3);
  257. break;
  258. case WorldViewProjectionMatrix:
  259. tempMat4.set(viewProjMatrix);
  260. tempMat4.multLocal(worldMatrix);
  261. u.setValue(VarType.Matrix4, tempMat4);
  262. break;
  263. case WorldMatrixInverse:
  264. tempMat4.multLocal(worldMatrix);
  265. tempMat4.invertLocal();
  266. u.setValue(VarType.Matrix4, tempMat4);
  267. break;
  268. case ViewMatrixInverse:
  269. tempMat4.set(viewMatrix);
  270. tempMat4.invertLocal();
  271. u.setValue(VarType.Matrix4, tempMat4);
  272. break;
  273. case ProjectionMatrixInverse:
  274. tempMat4.set(projMatrix);
  275. tempMat4.invertLocal();
  276. u.setValue(VarType.Matrix4, tempMat4);
  277. break;
  278. case ViewProjectionMatrixInverse:
  279. tempMat4.set(viewProjMatrix);
  280. tempMat4.invertLocal();
  281. u.setValue(VarType.Matrix4, tempMat4);
  282. break;
  283. case WorldViewMatrixInverse:
  284. tempMat4.set(viewMatrix);
  285. tempMat4.multLocal(worldMatrix);
  286. tempMat4.invertLocal();
  287. u.setValue(VarType.Matrix4, tempMat4);
  288. break;
  289. case NormalMatrixInverse:
  290. tempMat4.set(viewMatrix);
  291. tempMat4.multLocal(worldMatrix);
  292. tempMat4.toRotationMatrix(tempMat3);
  293. tempMat3.invertLocal();
  294. tempMat3.transposeLocal();
  295. tempMat3.invertLocal();
  296. u.setValue(VarType.Matrix3, tempMat3);
  297. break;
  298. case WorldViewProjectionMatrixInverse:
  299. tempMat4.set(viewProjMatrix);
  300. tempMat4.multLocal(worldMatrix);
  301. tempMat4.invertLocal();
  302. u.setValue(VarType.Matrix4, tempMat4);
  303. break;
  304. case ViewPort:
  305. tempVec4.set(viewX, viewY, viewWidth, viewHeight);
  306. u.setValue(VarType.Vector4, tempVec4);
  307. break;
  308. case Resolution:
  309. tempVec2.set(viewWidth, viewHeight);
  310. u.setValue(VarType.Vector2, tempVec2);
  311. break;
  312. case Aspect:
  313. float aspect = ((float) viewWidth) / viewHeight;
  314. u.setValue(VarType.Float, aspect);
  315. break;
  316. case FrustumNearFar:
  317. tempVec2.set(near, far);
  318. u.setValue(VarType.Vector2, tempVec2);
  319. break;
  320. case CameraPosition:
  321. u.setValue(VarType.Vector3, camLoc);
  322. break;
  323. case CameraDirection:
  324. u.setValue(VarType.Vector3, camDir);
  325. break;
  326. case CameraLeft:
  327. u.setValue(VarType.Vector3, camLeft);
  328. break;
  329. case CameraUp:
  330. u.setValue(VarType.Vector3, camUp);
  331. break;
  332. case Time:
  333. u.setValue(VarType.Float, timer.getTimeInSeconds());
  334. break;
  335. case Tpf:
  336. u.setValue(VarType.Float, timer.getTimePerFrame());
  337. break;
  338. case FrameRate:
  339. u.setValue(VarType.Float, timer.getFrameRate());
  340. break;
  341. }
  342. }
  343. assert vars.unlock();
  344. }
  345. /**
  346. * Set the material to use to render all future objects.
  347. * This overrides the material set on the geometry and renders
  348. * with the provided material instead.
  349. * Use null to clear the material and return renderer to normal
  350. * functionality.
  351. * @param mat
  352. */
  353. public void setForcedMaterial(Material mat) {
  354. forcedMaterial = mat;
  355. }
  356. public RenderState getForcedRenderState() {
  357. return forcedRenderState;
  358. }
  359. public void setForcedRenderState(RenderState forcedRenderState) {
  360. this.forcedRenderState = forcedRenderState;
  361. }
  362. public void setWorldMatrix(Matrix4f mat) {
  363. if (shader) {
  364. worldMatrix.set(mat);
  365. } else {
  366. renderer.setWorldMatrix(mat);
  367. }
  368. }
  369. public void renderGeometry(Geometry g) {
  370. if (g.isIgnoreTransform()) {
  371. setWorldMatrix(Matrix4f.IDENTITY);
  372. } else {
  373. setWorldMatrix(g.getWorldMatrix());
  374. }
  375. //if forcedTechnique we try to force it for render,
  376. //if it does not exists in the mat def, we check for forcedMaterial and render the geom if not null
  377. //else the geom is not rendered
  378. if (forcedTechnique != null) {
  379. if (g.getMaterial().getMaterialDef().getTechniqueDef(forcedTechnique) != null) {
  380. tmpTech = g.getMaterial().getActiveTechnique() != null ? g.getMaterial().getActiveTechnique().getDef().getName() : "Default";
  381. g.getMaterial().selectTechnique(forcedTechnique, this);
  382. // use geometry's material
  383. g.getMaterial().render(g, this);
  384. g.getMaterial().selectTechnique(tmpTech, this);
  385. //Reverted this part from revision 6197
  386. //If forcedTechnique does not exists, and frocedMaterial is not set, the geom MUST NOT be rendered
  387. } else if (forcedMaterial != null) {
  388. // use forced material
  389. forcedMaterial.render(g, this);
  390. }
  391. } else if (forcedMaterial != null) {
  392. // use forced material
  393. forcedMaterial.render(g, this);
  394. } else {
  395. g.getMaterial().render(g, this);
  396. }
  397. //re applying default render state at the end of the render to avoid depth write issues, MUST BE A BETTER WAY
  398. renderer.applyRenderState(RenderState.DEFAULT);
  399. }
  400. public void renderGeometryList(GeometryList gl) {
  401. for (int i = 0; i < gl.size(); i++) {
  402. renderGeometry(gl.get(i));
  403. }
  404. }
  405. /**
  406. * If a spatial is not inside the eye frustum, it
  407. * is still rendered in the shadow frustum through this
  408. * recursive method.
  409. * @param s
  410. * @param r
  411. */
  412. private void renderShadow(Spatial s, RenderQueue rq) {
  413. if (s instanceof Node) {
  414. Node n = (Node) s;
  415. List<Spatial> children = n.getChildren();
  416. for (int i = 0; i < children.size(); i++) {
  417. renderShadow(children.get(i), rq);
  418. }
  419. } else if (s instanceof Geometry) {
  420. Geometry gm = (Geometry) s;
  421. RenderQueue.ShadowMode shadowMode = s.getShadowMode();
  422. if (shadowMode != RenderQueue.ShadowMode.Off && shadowMode != RenderQueue.ShadowMode.Receive) {
  423. //forcing adding to shadow cast mode, culled objects doesn't have to be in the receiver queue
  424. rq.addToShadowQueue(gm, RenderQueue.ShadowMode.Cast);
  425. }
  426. }
  427. }
  428. public void preloadScene(Spatial scene) {
  429. if (scene instanceof Node) {
  430. // recurse for all children
  431. Node n = (Node) scene;
  432. List<Spatial> children = n.getChildren();
  433. for (int i = 0; i < children.size(); i++) {
  434. preloadScene(children.get(i));
  435. }
  436. } else if (scene instanceof Geometry) {
  437. // add to the render queue
  438. Geometry gm = (Geometry) scene;
  439. if (gm.getMaterial() == null) {
  440. throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
  441. }
  442. gm.getMaterial().preload(this);
  443. Mesh mesh = gm.getMesh();
  444. if (mesh != null) {
  445. for (Entry<VertexBuffer> entry : mesh.getBuffers()) {
  446. VertexBuffer buf = entry.getValue();
  447. if (buf.getData() != null) {
  448. renderer.updateBufferData(buf);
  449. }
  450. }
  451. }
  452. }
  453. }
  454. /**
  455. * Render scene graph
  456. * @param s
  457. * @param r
  458. * @param cam
  459. */
  460. public void renderScene(Spatial scene, ViewPort vp) {
  461. // check culling first.
  462. if (!scene.checkCulling(vp.getCamera())) {
  463. // move on to shadow-only render
  464. if (scene.getShadowMode() != RenderQueue.ShadowMode.Off || scene instanceof Node) {
  465. renderShadow(scene, vp.getQueue());
  466. }
  467. return;
  468. }
  469. scene.runControlRender(this, vp);
  470. if (scene instanceof Node) {
  471. // recurse for all children
  472. Node n = (Node) scene;
  473. List<Spatial> children = n.getChildren();
  474. for (int i = 0; i < children.size(); i++) {
  475. renderScene(children.get(i), vp);
  476. }
  477. } else if (scene instanceof Geometry) {
  478. // add to the render queue
  479. Geometry gm = (Geometry) scene;
  480. if (gm.getMaterial() == null) {
  481. throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
  482. }
  483. vp.getQueue().addToQueue(gm, scene.getQueueBucket());
  484. // add to shadow queue if needed
  485. RenderQueue.ShadowMode shadowMode = scene.getShadowMode();
  486. if (shadowMode != RenderQueue.ShadowMode.Off) {
  487. vp.getQueue().addToShadowQueue(gm, shadowMode);
  488. }
  489. }
  490. }
  491. public Camera getCurrentCamera() {
  492. return prevCam;
  493. }
  494. public Renderer getRenderer() {
  495. return renderer;
  496. }
  497. /**
  498. * Render the given viewport queues, flushing the geometryList
  499. * @param vp the viewport
  500. */
  501. public void flushQueue(ViewPort vp) {
  502. renderViewPortQueues(vp, true);
  503. }
  504. public void clearQueue(ViewPort vp) {
  505. vp.getQueue().clear();
  506. }
  507. //Nehon 08/18/2010 changed flushQueue to renderViewPortQueues with a flush boolean param
  508. /**
  509. * Render the given viewport queues
  510. * @param vp the viewport
  511. * @param flush true to flush geometryList
  512. */
  513. public void renderViewPortQueues(ViewPort vp, boolean flush) {
  514. RenderQueue rq = vp.getQueue();
  515. Camera cam = vp.getCamera();
  516. boolean depthRangeChanged = false;
  517. // render opaque objects with default depth range
  518. // opaque objects are sorted front-to-back, reducing overdraw
  519. rq.renderQueue(Bucket.Opaque, this, cam, flush);
  520. // render the sky, with depth range set to the farthest
  521. if (!rq.isQueueEmpty(Bucket.Sky)) {
  522. renderer.setDepthRange(1, 1);
  523. rq.renderQueue(Bucket.Sky, this, cam, flush);
  524. depthRangeChanged = true;
  525. }
  526. // transparent objects are last because they require blending with the
  527. // rest of the scene's objects. Consequently, they are sorted
  528. // back-to-front.
  529. if (!rq.isQueueEmpty(Bucket.Transparent)) {
  530. if (depthRangeChanged) {
  531. renderer.setDepthRange(0, 1);
  532. depthRangeChanged = false;
  533. }
  534. rq.renderQueue(Bucket.Transparent, this, cam, flush);
  535. }
  536. if (!rq.isQueueEmpty(Bucket.Gui)) {
  537. renderer.setDepthRange(0, 0);
  538. setCamera(cam, true);
  539. rq.renderQueue(Bucket.Gui, this, cam, flush);
  540. setCamera(cam, false);
  541. depthRangeChanged = true;
  542. }
  543. // restore range to default
  544. if (depthRangeChanged) {
  545. renderer.setDepthRange(0, 1);
  546. }
  547. }
  548. private void setViewPort(Camera cam) {
  549. // this will make sure to update viewport only if needed
  550. if (cam != prevCam || cam.isViewportChanged()) {
  551. viewX = (int) (cam.getViewPortLeft() * cam.getWidth());
  552. viewY = (int) (cam.getViewPortBottom() * cam.getHeight());
  553. viewWidth = (int) ((cam.getViewPortRight() - cam.getViewPortLeft()) * cam.getWidth());
  554. viewHeight = (int) ((cam.getViewPortTop() - cam.getViewPortBottom()) * cam.getHeight());
  555. renderer.setViewPort(viewX, viewY, viewWidth, viewHeight);
  556. renderer.setClipRect(viewX, viewY, viewWidth, viewHeight);
  557. cam.clearViewportChanged();
  558. prevCam = cam;
  559. // float translateX = viewWidth == viewX ? 0 : -(viewWidth + viewX) / (viewWidth - viewX);
  560. // float translateY = viewHeight == viewY ? 0 : -(viewHeight + viewY) / (viewHeight - viewY);
  561. // float scaleX = viewWidth == viewX ? 1f : 2f / (viewWidth - viewX);
  562. // float scaleY = viewHeight == viewY ? 1f : 2f / (viewHeight - viewY);
  563. //
  564. // orthoMatrix.loadIdentity();
  565. // orthoMatrix.setTranslation(translateX, translateY, 0);
  566. // orthoMatrix.setScale(scaleX, scaleY, 0);
  567. orthoMatrix.loadIdentity();
  568. orthoMatrix.setTranslation(-1f, -1f, 0f);
  569. orthoMatrix.setScale(2f / cam.getWidth(), 2f / cam.getHeight(), 0f);
  570. }
  571. }
  572. private void setViewProjection(Camera cam, boolean ortho) {
  573. if (shader) {
  574. if (ortho) {
  575. viewMatrix.set(Matrix4f.IDENTITY);
  576. projMatrix.set(orthoMatrix);
  577. viewProjMatrix.set(orthoMatrix);
  578. } else {
  579. viewMatrix.set(cam.getViewMatrix());
  580. projMatrix.set(cam.getProjectionMatrix());
  581. viewProjMatrix.set(cam.getViewProjectionMatrix());
  582. }
  583. camLoc.set(cam.getLocation());
  584. cam.getLeft(camLeft);
  585. cam.getUp(camUp);
  586. cam.getDirection(camDir);
  587. near = cam.getFrustumNear();
  588. far = cam.getFrustumFar();
  589. } else {
  590. if (ortho) {
  591. renderer.setViewProjectionMatrices(Matrix4f.IDENTITY, orthoMatrix);
  592. } else {
  593. renderer.setViewProjectionMatrices(cam.getViewMatrix(),
  594. cam.getProjectionMatrix());
  595. }
  596. }
  597. }
  598. public void setCamera(Camera cam, boolean ortho) {
  599. setViewPort(cam);
  600. setViewProjection(cam, ortho);
  601. }
  602. /**
  603. * Draws the viewport but doesn't invoke processors.
  604. * @param vp
  605. */
  606. public void renderViewPortRaw(ViewPort vp) {
  607. setCamera(vp.getCamera(), false);
  608. List<Spatial> scenes = vp.getScenes();
  609. for (int i = scenes.size() - 1; i >= 0; i--) {
  610. renderScene(scenes.get(i), vp);
  611. }
  612. flushQueue(vp);
  613. }
  614. public void renderViewPort(ViewPort vp, float tpf) {
  615. if (!vp.isEnabled()) {
  616. return;
  617. }
  618. List<SceneProcessor> processors = vp.getProcessors();
  619. if (processors.size() == 0) {
  620. processors = null;
  621. }
  622. if (processors != null) {
  623. for (SceneProcessor proc : processors) {
  624. if (!proc.isInitialized()) {
  625. proc.initialize(this, vp);
  626. }
  627. proc.preFrame(tpf);
  628. }
  629. }
  630. renderer.setFrameBuffer(vp.getOutputFrameBuffer());
  631. setCamera(vp.getCamera(), false);
  632. if (vp.isClearDepth() || vp.isClearColor() || vp.isClearStencil()) {
  633. if (vp.isClearColor()) {
  634. renderer.setBackgroundColor(vp.getBackgroundColor());
  635. }
  636. renderer.clearBuffers(vp.isClearColor(),
  637. vp.isClearDepth(),
  638. vp.isClearStencil());
  639. }
  640. List<Spatial> scenes = vp.getScenes();
  641. for (int i = scenes.size() - 1; i >= 0; i--) {
  642. renderScene(scenes.get(i), vp);
  643. }
  644. if (processors != null) {
  645. for (SceneProcessor proc : processors) {
  646. proc.postQueue(vp.getQueue());
  647. }
  648. }
  649. flushQueue(vp);
  650. if (processors != null) {
  651. for (SceneProcessor proc : processors) {
  652. proc.postFrame(vp.getOutputFrameBuffer());
  653. }
  654. }
  655. // clear any remaining spatials that were not rendered.
  656. clearQueue(vp);
  657. }
  658. public void render(float tpf) {
  659. if (renderer instanceof NullRenderer) {
  660. return;
  661. }
  662. this.shader = renderer.getCaps().contains(Caps.GLSL100);
  663. for (int i = 0; i < preViewPorts.size(); i++) {
  664. renderViewPort(preViewPorts.get(i), tpf);
  665. }
  666. for (int i = 0; i < viewPorts.size(); i++) {
  667. renderViewPort(viewPorts.get(i), tpf);
  668. }
  669. for (int i = 0; i < postViewPorts.size(); i++) {
  670. renderViewPort(postViewPorts.get(i), tpf);
  671. }
  672. }
  673. //Remy - 09/14/2010 - added a setter for the timer in order to correctly populate g_Time and g_Tpf in the shaders
  674. public void setTimer(Timer timer) {
  675. this.timer = timer;
  676. }
  677. public String getForcedTechnique() {
  678. return forcedTechnique;
  679. }
  680. public void setForcedTechnique(String forcedTechnique) {
  681. this.forcedTechnique = forcedTechnique;
  682. }
  683. public void setAlphaToCoverage(boolean value) {
  684. renderer.setAlphaToCoverage(value);
  685. }
  686. }