From b6d41dd8c8f5b32140cd783a74448a7f658a3669 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 6 Dec 2001 02:07:37 +0000 Subject: [PATCH] rewrite cameras to use new lens interface --- direct/src/directtools/DirectSelection.py | 4 +- direct/src/directtools/DirectSession.py | 39 +- direct/src/leveleditor/LevelEditor.py | 4 +- direct/src/showbase/ShowBase.py | 49 +- direct/src/showbase/showBase.cxx | 10 +- direct/src/tkpanels/DirectSessionPanel.py | 4 +- panda/src/chancfg/chancfg.cxx | 14 +- panda/src/collide/collide_headers.h | 4 +- panda/src/collide/collisionRay.I | 12 +- panda/src/collide/collisionRay.cxx | 21 +- panda/src/collide/collisionRay.h | 6 +- panda/src/collide/collisionSegment.I | 12 +- panda/src/collide/collisionSegment.cxx | 25 +- panda/src/collide/collisionSegment.h | 6 +- panda/src/cull/cullTraverser.cxx | 2 +- panda/src/display/displayRegion.I | 8 +- panda/src/display/displayRegion.h | 6 +- panda/src/display/graphicsStateGuardian.I | 14 +- panda/src/display/graphicsStateGuardian.h | 8 +- panda/src/dxgsg/dxGraphicsStateGuardian.cxx | 52 +- panda/src/dxgsg/dxGraphicsStateGuardian.h | 4 +- panda/src/effects/lensFlareNode.cxx | 11 +- panda/src/framework/framework.cxx | 9 +- panda/src/glgsg/glGraphicsStateGuardian.cxx | 110 +- panda/src/glgsg/glGraphicsStateGuardian.h | 4 +- panda/src/gobj/Sources.pp | 17 +- panda/src/gobj/config_gobj.cxx | 12 +- panda/src/gobj/gobj_composite2.cxx | 6 +- panda/src/gobj/lens.I | 367 +++++ panda/src/gobj/lens.cxx | 1291 +++++++++++++++++ panda/src/gobj/lens.h | 242 +++ panda/src/gobj/orthoProjection.I | 41 - panda/src/gobj/orthoProjection.cxx | 142 -- .../orthographicLens.I} | 36 +- panda/src/gobj/orthographicLens.cxx | 114 ++ panda/src/gobj/orthographicLens.h | 75 + ...spectiveProjection.I => perspectiveLens.I} | 30 +- panda/src/gobj/perspectiveLens.cxx | 146 ++ .../{orthoProjection.h => perspectiveLens.h} | 51 +- panda/src/gobj/perspectiveProjection.cxx | 219 --- panda/src/gobj/perspectiveProjection.h | 79 - panda/src/gobj/projection.cxx | 81 -- panda/src/gobj/projection.h | 72 - panda/src/gsgbase/graphicsStateGuardianBase.h | 4 +- panda/src/light/directionalLight.cxx | 1 - panda/src/light/spotlight.cxx | 15 +- panda/src/light/spotlight.h | 8 +- panda/src/linmath/cmath.I | 16 + panda/src/linmath/cmath.h | 4 + panda/src/mathutil/boundingHexahedron.cxx | 19 + panda/src/mathutil/boundingHexahedron.h | 4 + panda/src/sgattrib/billboardTransition.cxx | 6 +- panda/src/sgraph/Sources.pp | 8 +- panda/src/sgraph/camera.cxx | 110 +- panda/src/sgraph/camera.h | 28 +- panda/src/sgraph/config_sgraph.cxx | 4 +- panda/src/sgraph/geomTransformer.cxx | 2 +- panda/src/sgraph/lensNode.I | 88 ++ panda/src/sgraph/lensNode.cxx | 85 ++ panda/src/sgraph/lensNode.h | 80 + panda/src/sgraph/projectionNode.cxx | 367 ----- panda/src/sgraph/projectionNode.h | 97 -- panda/src/sgraph/sgraph_composite2.cxx | 2 +- .../src/sgraphutil/directRenderTraverser.cxx | 6 +- panda/src/sgraphutil/frustumCullTraverser.I | 39 +- panda/src/shader/shader.I | 6 +- panda/src/shader/shader.h | 10 +- panda/src/shader/spheretexHighlighter.cxx | 2 +- panda/src/shader/spheretexReflector.cxx | 19 +- panda/src/switchnode/LODNode.cxx | 6 +- panda/src/testbed/demo.cxx | 117 -- panda/src/testbed/herc.cxx | 8 +- panda/src/testbed/min_herc.cxx | 10 +- panda/src/testbed/min_shader.cxx | 23 +- panda/src/testbed/panda.cxx | 19 +- panda/src/testbed/shader_test.cxx | 12 +- 76 files changed, 2921 insertions(+), 1763 deletions(-) create mode 100644 panda/src/gobj/lens.I create mode 100644 panda/src/gobj/lens.cxx create mode 100644 panda/src/gobj/lens.h delete mode 100644 panda/src/gobj/orthoProjection.I delete mode 100644 panda/src/gobj/orthoProjection.cxx rename panda/src/{sgraph/projectionNode.I => gobj/orthographicLens.I} (62%) create mode 100644 panda/src/gobj/orthographicLens.cxx create mode 100644 panda/src/gobj/orthographicLens.h rename panda/src/gobj/{perspectiveProjection.I => perspectiveLens.I} (61%) create mode 100644 panda/src/gobj/perspectiveLens.cxx rename panda/src/gobj/{orthoProjection.h => perspectiveLens.h} (52%) delete mode 100644 panda/src/gobj/perspectiveProjection.cxx delete mode 100644 panda/src/gobj/perspectiveProjection.h delete mode 100644 panda/src/gobj/projection.cxx delete mode 100644 panda/src/gobj/projection.h create mode 100644 panda/src/sgraph/lensNode.I create mode 100644 panda/src/sgraph/lensNode.cxx create mode 100644 panda/src/sgraph/lensNode.h delete mode 100644 panda/src/sgraph/projectionNode.cxx delete mode 100644 panda/src/sgraph/projectionNode.h diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index de2892be04..be08a8fe29 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -487,8 +487,8 @@ class SelectionRay: def pick(self, targetNodePath, mouseX, mouseY): # Determine ray direction based upon the mouse coordinates - # Note! This has to be a cam object (of type ProjectionNode) - self.ray.setProjection( base.cam.node(), mouseX, mouseY ) + # Note! This has to be a cam object (of type LensNode) + self.ray.setFromLens( base.camNode, mouseX, mouseY ) self.ct.traverse( targetNodePath.node() ) self.numEntries = self.cq.getNumEntries() self.cq.sortEntries() diff --git a/direct/src/directtools/DirectSession.py b/direct/src/directtools/DirectSession.py index 372569d566..e5abc117e8 100644 --- a/direct/src/directtools/DirectSession.py +++ b/direct/src/directtools/DirectSession.py @@ -782,15 +782,15 @@ class DisplayRegionList(PandaObject): def setNearFar(self, near, far): for dr in self.displayRegionList: - dr.camNode.setNearFar(near, far) + dr.camLens.setNearFar(near, far) def setNear(self, near): for dr in self.displayRegionList: - dr.camNode.setNear(near) + dr.camLens.setNear(near) def setFar(self, far): for dr in self.displayRegionList: - dr.camNode.setFar(far) + dr.camLens.setFar(far) def setFov(self, hfov, vfov): for dr in self.displayRegionList: @@ -850,7 +850,8 @@ class DisplayRegionContext: def __init__(self, win, cam, group): self.win = win self.cam = cam - self.camNode = self.cam.getNode(0) + self.camNode = self.cam.node() + self.camLens = self.camNode.getLens() self.group = group self.iRay = SelectionRay(self.cam) self.nearVec = Vec3(0) @@ -889,44 +890,42 @@ class DisplayRegionContext: # The following take into consideration sideways displays def getHfov(self): if self.isSideways: - return self.camNode.getVfov() + return self.camLens.getVfov() else: - return self.camNode.getHfov() + return self.camLens.getHfov() def getVfov(self): if self.isSideways: - return self.camNode.getHfov() + return self.camLens.getHfov() else: - return self.camNode.getVfov() + return self.camLens.getVfov() def setHfov(self,hfov): if self.isSideways: - self.camNode.setVfov(hfov) + self.camLens.setFov(self.camLens.getHfov(), hfov) else: - self.camNode.setHfov(hfov) + self.camLens.setFov(hfov, self.camLens.getVfov()) def setVfov(self,vfov): if self.isSideways: - self.camNode.setHfov(vfov) + self.camLens.setFov(vfov, self.camLens.getVfov()) else: - self.camNode.setVfov(vfov) + self.camLens.setFov(self.camLens.getHfov(), vfov) def setFov(self,hfov,vfov): if self.isSideways: - self.camNode.setVfov(hfov) - self.camNode.setHfov(vfov) + self.camLens.setFov(vfov, hfov) else: - self.camNode.setHfov(hfov) - self.camNode.setVfov(vfov) + self.camLens.setFov(hfov, vfov) def camUpdate(self): # Window Data self.width = self.win.getWidth() self.height = self.win.getHeight() - self.near = self.camNode.getNear() - self.far = self.camNode.getFar() - self.fovH = self.camNode.getHfov() - self.fovV = self.camNode.getVfov() + self.near = self.camLens.getNear() + self.far = self.camLens.getFar() + self.fovH = self.camLens.getHfov() + self.fovV = self.camLens.getVfov() self.nearWidth = math.tan(deg2Rad(self.fovH * 0.5)) * self.near * 2.0 self.nearHeight = math.tan(deg2Rad(self.fovV * 0.5)) * self.near * 2.0 self.left = -self.nearWidth * 0.5 diff --git a/direct/src/leveleditor/LevelEditor.py b/direct/src/leveleditor/LevelEditor.py index df43d987c8..9f58ee92ac 100644 --- a/direct/src/leveleditor/LevelEditor.py +++ b/direct/src/leveleditor/LevelEditor.py @@ -514,8 +514,8 @@ class LevelEditor(NodePath, PandaObject): 'y-ring', 'y-disc', 'z-post']) # Initialize camera - base.cam.node().setNear(1.0) - base.cam.node().setFar(3000) + base.camLens.setNear(1.0) + base.camLens.setFar(3000) direct.camera.setPos(0,-10,10) # Initialize drive mode self.configureDriveModeCollisionData() diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index ea6d3b9256..0d2d1bcf0b 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -112,9 +112,14 @@ class ShowBase: self.camList.append( camera.find('**/+Camera') ) # Set the default camera self.cam = self.camera.find('**/+Camera') - # If you need to use the camera node, use camNode instead - # of calling cam.node() to save the FFI overhead + + # If you need to get a handle to the camera node itself, use + # self.camNode. self.camNode = self.cam.node() + # If you need to adjust camera parameters, like fov or + # near/far clipping planes, use self.camLens + self.camLens = self.camNode.getLens() + # Set up a 2-d layer for drawing things behind Gui labels. self.render2d = NodePath(setupPanda2d(self.win, "render2d")) @@ -131,9 +136,7 @@ class ShowBase: self.aspect2d.setScale(1.0 / self.aspectRatio, 1.0, 1.0) # And let's enforce that aspect ratio on the camera. - hfov = self.camNode.getHfov() - vfov = hfov / self.aspectRatio - self.camNode.setFov(hfov, vfov) + self.camLens.setAspectRatio(self.aspectRatio) # It's important to know the bounds of the aspect2d screen. self.a2dTop = 1.0 @@ -141,17 +144,6 @@ class ShowBase: self.a2dLeft = -self.aspectRatio self.a2dRight = self.aspectRatio - # Set up an auxiliary 3-d layer for rendering floating heads - # or other 3-d objects on top of text or widgets in the 2-d - # layer. We set it up with a camera that specifically shares - # the projection with the default camera, so that when we - # change the default camera's parameters, it changes this one - # too. - self.renderAux = NodePath(NamedNode('renderAux')) - self.camAux = self.renderAux.attachNewNode(Camera('camAux')) - self.camAux.node().shareProjection(self.cam.node().getProjection()) - addRenderLayer(self.win, self.renderAux.node(), self.camAux.node()) - # We create both a MouseAndKeyboard object and a MouseWatcher object # for the window. The MouseAndKeyboard generates mouse events and # mouse button/keyboard events; the MouseWatcher passes them through @@ -543,6 +535,10 @@ class ShowBase: self.oobeCamera = self.hidden.attachNewNode('oobeCamera') self.oobeCameraTrackball = self.oobeCamera.attachNewNode('oobeCameraTrackball') + self.oobeLens = PerspectiveLens() + self.oobeLens.setAspectRatio(self.aspectRatio) + self.oobeLens.setNearFar(0.1, 10000.0) + self.oobeLens.setFov(52.0) self.oobeControl = DataValve.Control() self.mouseValve.node().setControl(1, self.oobeControl) self.oobeTrackball = self.mouseValve.attachNewNode(Trackball('oobeTrackball'), 1) @@ -555,6 +551,7 @@ class ShowBase: if self.oobeVis: self.oobeVis.arc().setFinal(1) self.oobeCullFrustum = None + self.oobeCullFrustumVis = None # Make sure the MouseValve is monitoring the Control key. mods = ModifierButtons(self.mouseValve.node().getModifierButtons()) @@ -573,6 +570,7 @@ class ShowBase: if self.oobeVis: self.oobeVis.reparentTo(self.hidden) self.cam.reparentTo(self.camera) + self.camNode.setLens(self.camLens) self.oobeCamera.reparentTo(self.hidden) self.oobeMode = 0 else: @@ -592,8 +590,7 @@ class ShowBase: self.mouseValve.node().setFineControl(0, self.oobeButtonEventsType, self.onControl) # Make oobeCamera be a sibling of wherever camera is now. - cameraParent = NodePath(self.camera) - cameraParent.shorten(1) + cameraParent = self.camera.getParent() self.oobeCamera.reparentTo(cameraParent) self.oobeCamera.clearMat() @@ -603,6 +600,7 @@ class ShowBase: self.oobeTrackball.node().setMat(mat) self.cam.reparentTo(self.oobeCameraTrackball) + self.camNode.setLens(self.oobeLens) if self.oobeVis: self.oobeVis.reparentTo(self.camera) self.oobeMode = 1 @@ -623,10 +621,17 @@ class ShowBase: if self.oobeCullFrustum == None: # Enable OOBE culling. - pnode = ProjectionNode('oobeCull') - pnode.setProjection(self.camNode.getProjection()) + pnode = LensNode('oobeCull') + pnode.setLens(self.camLens) self.oobeCullFrustum = self.camera.attachNewNode(pnode) + # Create a visible representation of the frustum. + geom = self.camLens.makeGeometry() + if geom != None: + gn = GeomNode('frustum') + gn.addGeom(geom) + self.oobeCullFrustumVis = self.oobeVis.attachNewNode(gn) + # Assign each DisplayRegion shared by the camera to use # this cull frustum. numDrs = self.camNode.getNumDrs() @@ -646,6 +651,10 @@ class ShowBase: self.oobeCullFrustum.removeNode() self.oobeCullFrustum = None + if self.oobeCullFrustumVis != None: + self.oobeCullFrustumVis.removeNode() + self.oobeCullFrustumVis = None + def screenshot(self, namePrefix='screenshot'): # Get the current date and time to uniquify the image (down to the second) date = time.ctime(time.time()) diff --git a/direct/src/showbase/showBase.cxx b/direct/src/showbase/showBase.cxx index 1920d929b5..ef2350257d 100644 --- a/direct/src/showbase/showBase.cxx +++ b/direct/src/showbase/showBase.cxx @@ -40,8 +40,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -180,9 +179,10 @@ setup_panda_2d(GraphicsWindow *win, const string &graph_name) { Camera *cam2d = new Camera("cam2d"); new RenderRelation(render2d, cam2d); - Frustumf frustum2d; - frustum2d.make_ortho(-1000.0f,1000.0f); - cam2d->set_projection(OrthoProjection(frustum2d)); + PT(Lens) lens = new OrthographicLens; + lens->set_film_size(2.0); + lens->set_near_far(-1000.0f, 1000.0f); + cam2d->set_lens(lens); add_render_layer(win, render2d_top, cam2d); diff --git a/direct/src/tkpanels/DirectSessionPanel.py b/direct/src/tkpanels/DirectSessionPanel.py index 463564e98f..46a09adbf5 100644 --- a/direct/src/tkpanels/DirectSessionPanel.py +++ b/direct/src/tkpanels/DirectSessionPanel.py @@ -736,12 +736,12 @@ class DirectSessionPanel(AppShell): def setNear(self, near): dr = self.activeDisplayRegion if dr: - dr.camNode.setNear(near) + dr.camLens.setNear(near) def setFar(self, far): dr = self.activeDisplayRegion if dr: - dr.camNode.setFar(far) + dr.camLens.setFar(far) def setHFov(self, hFov): dr = self.activeDisplayRegion diff --git a/panda/src/chancfg/chancfg.cxx b/panda/src/chancfg/chancfg.cxx index 58fac57b99..0e5b93b3bf 100644 --- a/panda/src/chancfg/chancfg.cxx +++ b/panda/src/chancfg/chancfg.cxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -299,15 +299,17 @@ void ChanConfig::chan_eval(GraphicsWindow* win, WindowItem& W, LayoutItem& L, break; } - Frustumf frust; - frust.make_perspective(hFov, vFov, 1., 10000.); - cam->set_projection(PerspectiveProjection(frust)); + PT(Lens) lens = new PerspectiveLens; + lens->set_fov(hFov, vFov); + lens->set_near_far(1.0f, 10000.0f); + cam->set_lens(lens); + // hfov and vfov for camera are switched from what was specified // if the orientation is sideways. if (chancfg_cat->is_debug()) chancfg_cat->debug() << "ChanEval:: camera hfov = " - << cam->get_hfov() << " vfov = " - << cam->get_vfov() << endl; + << lens->get_hfov() << " vfov = " + << lens->get_vfov() << endl; cam->set_scene(render); RenderRelation *tocam = new RenderRelation(camera[W.getCameraGroup(j)], cam); diff --git a/panda/src/collide/collide_headers.h b/panda/src/collide/collide_headers.h index 340c4a3193..a59a76deab 100644 --- a/panda/src/collide/collide_headers.h +++ b/panda/src/collide/collide_headers.h @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/panda/src/collide/collisionRay.I b/panda/src/collide/collisionRay.I index 588321934a..deb0cf2297 100644 --- a/panda/src/collide/collisionRay.I +++ b/panda/src/collide/collisionRay.I @@ -22,7 +22,7 @@ // Description: Creates an invalid ray. This isn't terribly useful; // it's expected that the user will subsequently adjust // the ray via set_origin()/set_direction() or -// set_projection(). +// set_from_lens(). //////////////////////////////////////////////////////////////////// INLINE CollisionRay:: CollisionRay() : @@ -135,15 +135,15 @@ get_direction() const { } //////////////////////////////////////////////////////////////////// -// Function: CollisionRay::set_projection +// Function: CollisionRay::set_from_lens // Access: Public -// Description: Accepts a ProjectionNode and a 2-d point in the range +// Description: Accepts a LensNode and a 2-d point in the range // [-1,1]. Sets the CollisionRay so that it begins at -// the ProjectionNode's near plane and extends to +// the LensNode's near plane and extends to // infinity, making it suitable for picking objects from // the screen given a camera and a mouse location. //////////////////////////////////////////////////////////////////// INLINE bool CollisionRay:: -set_projection(ProjectionNode *camera, float px, float py) { - return set_projection(camera, LPoint2f(px, py)); +set_from_lens(LensNode *camera, float px, float py) { + return set_from_lens(camera, LPoint2f(px, py)); } diff --git a/panda/src/collide/collisionRay.cxx b/panda/src/collide/collisionRay.cxx index 2e2a7bfc96..b1deca34f4 100644 --- a/panda/src/collide/collisionRay.cxx +++ b/panda/src/collide/collisionRay.cxx @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include TypeHandle CollisionRay::_type_handle; @@ -88,11 +88,11 @@ output(ostream &out) const { } //////////////////////////////////////////////////////////////////// -// Function: CollisionRay::set_projection +// Function: CollisionRay::set_from_lens // Access: Public -// Description: Accepts a ProjectionNode and a 2-d point in the range +// Description: Accepts a LensNode and a 2-d point in the range // [-1,1]. Sets the CollisionRay so that it begins at -// the ProjectionNode's near plane and extends to +// the LensNode's near plane and extends to // infinity, making it suitable for picking objects from // the screen given a camera and a mouse location. // @@ -100,15 +100,20 @@ output(ostream &out) const { // otherwise. //////////////////////////////////////////////////////////////////// bool CollisionRay:: -set_projection(ProjectionNode *camera, const LPoint2f &point) { - Projection *proj = camera->get_projection(); +set_from_lens(LensNode *camera, const LPoint2f &point) { + Lens *lens = camera->get_lens(); bool success = true; - if (!proj->extrude(point, _origin, _direction)) { + LPoint3f near_point, far_point; + if (!lens->extrude(point, near_point, far_point)) { _origin = LPoint3f::origin(); _direction = LVector3f::forward(); success = false; + } else { + _origin = near_point; + _direction = far_point - near_point; } + mark_bound_stale(); mark_viz_stale(); diff --git a/panda/src/collide/collisionRay.h b/panda/src/collide/collisionRay.h index d87d8fc65e..6f40215f48 100644 --- a/panda/src/collide/collisionRay.h +++ b/panda/src/collide/collisionRay.h @@ -23,7 +23,7 @@ #include "collisionSolid.h" -class ProjectionNode; +class LensNode; /////////////////////////////////////////////////////////////////// // Class : CollisionRay @@ -63,8 +63,8 @@ PUBLISHED: INLINE void set_direction(float x, float y, float z); INLINE const LVector3f &get_direction() const; - bool set_projection(ProjectionNode *camera, const LPoint2f &point); - INLINE bool set_projection(ProjectionNode *camera, float px, float py); + bool set_from_lens(LensNode *camera, const LPoint2f &point); + INLINE bool set_from_lens(LensNode *camera, float px, float py); protected: virtual void recompute_bound(); diff --git a/panda/src/collide/collisionSegment.I b/panda/src/collide/collisionSegment.I index 913466060a..625b9ea2ca 100644 --- a/panda/src/collide/collisionSegment.I +++ b/panda/src/collide/collisionSegment.I @@ -22,7 +22,7 @@ // Description: Creates an invalid segment. This isn't terribly useful; // it's expected that the user will subsequently adjust // the segment via set_origin()/set_direction() or -// set_projection(). +// set_from_lens(). //////////////////////////////////////////////////////////////////// INLINE CollisionSegment:: CollisionSegment() : @@ -138,15 +138,15 @@ get_point_b() const { } //////////////////////////////////////////////////////////////////// -// Function: CollisionSegment::set_projection +// Function: CollisionSegment::set_from_lens // Access: Public -// Description: Accepts a ProjectionNode and a 2-d point in the range +// Description: Accepts a LensNode and a 2-d point in the range // [-1,1]. Sets the CollisionSegment so that it begins at -// the ProjectionNode's near plane and extends to the +// the LensNode's near plane and extends to the // far plane, making it suitable for picking objects // from the screen given a camera and a mouse location. //////////////////////////////////////////////////////////////////// INLINE bool CollisionSegment:: -set_projection(ProjectionNode *camera, float px, float py) { - return set_projection(camera, LPoint2f(px, py)); +set_from_lens(LensNode *camera, float px, float py) { + return set_from_lens(camera, LPoint2f(px, py)); } diff --git a/panda/src/collide/collisionSegment.cxx b/panda/src/collide/collisionSegment.cxx index e4eb864aa4..871c619661 100644 --- a/panda/src/collide/collisionSegment.cxx +++ b/panda/src/collide/collisionSegment.cxx @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -91,11 +91,11 @@ output(ostream &out) const { } //////////////////////////////////////////////////////////////////// -// Function: CollisionSegment::set_projection +// Function: CollisionSegment::set_from_lens // Access: Public -// Description: Accepts a ProjectionNode and a 2-d point in the range +// Description: Accepts a LensNode and a 2-d point in the range // [-1,1]. Sets the CollisionSegment so that it begins at -// the ProjectionNode's near plane and extends to the +// the LensNode's near plane and extends to the // far plane, making it suitable for picking objects // from the screen given a camera and a mouse location. // @@ -103,21 +103,16 @@ output(ostream &out) const { // otherwise. //////////////////////////////////////////////////////////////////// bool CollisionSegment:: -set_projection(ProjectionNode *camera, const LPoint2f &point) { - Projection *proj = camera->get_projection(); +set_from_lens(LensNode *camera, const LPoint2f &point) { + Lens *proj = camera->get_lens(); bool success = true; - LPoint3f origin; - LVector3f direction; - if (!proj->extrude(point, origin, direction)) { - origin = LPoint3f::origin(); - direction = LVector3f::forward(); + if (!proj->extrude(point, _a, _b)) { + _a = LPoint3f::origin(); + _b = _a + LVector3f::forward(); success = false; } - _a = origin; - _b = origin + direction; - mark_bound_stale(); mark_viz_stale(); diff --git a/panda/src/collide/collisionSegment.h b/panda/src/collide/collisionSegment.h index 911a271159..417edf59d5 100644 --- a/panda/src/collide/collisionSegment.h +++ b/panda/src/collide/collisionSegment.h @@ -23,7 +23,7 @@ #include "collisionSolid.h" -class ProjectionNode; +class LensNode; /////////////////////////////////////////////////////////////////// // Class : CollisionSegment @@ -66,8 +66,8 @@ PUBLISHED: INLINE void set_point_b(float x, float y, float z); INLINE const LPoint3f &get_point_b() const; - bool set_projection(ProjectionNode *camera, const LPoint2f &point); - INLINE bool set_projection(ProjectionNode *camera, float px, float py); + bool set_from_lens(LensNode *camera, const LPoint2f &point); + INLINE bool set_from_lens(LensNode *camera, float px, float py); protected: virtual void recompute_bound(); diff --git a/panda/src/cull/cullTraverser.cxx b/panda/src/cull/cullTraverser.cxx index 49c600c899..a2351c8d9d 100644 --- a/panda/src/cull/cullTraverser.cxx +++ b/panda/src/cull/cullTraverser.cxx @@ -263,7 +263,7 @@ traverse(Node *root, LMatrix4f rel_from_camera; NodeTransitionWrapper ntw(TransformTransition::get_class_type()); const DisplayRegion *dr = _gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); + LensNode *camera = dr->get_cull_frustum(); wrt(camera, root, begin(), end(), ntw, get_graph_type()); const TransformTransition *tt; if (get_transition_into(tt, ntw)) { diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index 05e0c258cf..4c793c7020 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -105,7 +105,7 @@ get_camera() const { //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::set_cull_frustum // Access: Public -// Description: Sets the ProjectionNode that will be used to perform +// Description: Sets the LensNode that will be used to perform // view-frustum culling for this particular // DisplayRegion. Normally, this is the same as the // camera (and is implicitly set when set_camera() is @@ -115,18 +115,18 @@ get_camera() const { // observed from a third-person perspective. //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: -set_cull_frustum(ProjectionNode *cull_frustum) { +set_cull_frustum(LensNode *cull_frustum) { _cull_frustum = cull_frustum; } //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::get_cull_frustum // Access: Public -// Description: Returns the ProjectionNode that will be used to +// Description: Returns the LensNode that will be used to // perform view-frustum culling for this particular // DisplayRegion. See set_cull_frustum(). //////////////////////////////////////////////////////////////////// -INLINE ProjectionNode *DisplayRegion:: +INLINE LensNode *DisplayRegion:: get_cull_frustum() const { return _cull_frustum; } diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index eba3e634c7..fc09afabd9 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -65,8 +65,8 @@ PUBLISHED: void set_camera(Camera *camera); INLINE Camera *get_camera() const; - INLINE void set_cull_frustum(ProjectionNode *cull_frustum); - INLINE ProjectionNode *get_cull_frustum() const; + INLINE void set_cull_frustum(LensNode *cull_frustum); + INLINE LensNode *get_cull_frustum() const; INLINE void set_active(bool active); INLINE bool is_active() const; @@ -94,7 +94,7 @@ protected: GraphicsLayer *_layer; PT(Camera) _camera; - PT(ProjectionNode) _cull_frustum; + PT(LensNode) _cull_frustum; bool _active; diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 7db28d017d..d61b3133ee 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -129,15 +129,17 @@ get_state() const { */ //////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::get_current_projection_node +// Function: GraphicsStateGuardian::get_current_camera // Access: Public // Description: Returns the node currently being used as the -// projection node (i.e. the camera) for this scene, as -// set by the last call to render_subgraph(). +// camera for this scene, as set by the last call to +// render_subgraph(). This actually might be any kind +// of LensNode, not specifically a Camera node, although +// it will usually be a Camera. //////////////////////////////////////////////////////////////////// -INLINE ProjectionNode *GraphicsStateGuardian:: -get_current_projection_node(void) const { - return _current_projection_node; +INLINE LensNode *GraphicsStateGuardian:: +get_current_camera(void) const { + return _current_camera; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 3e86e88d0b..ce66750a08 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -105,9 +105,9 @@ public: virtual void prepare_display_region()=0; virtual void render_frame()=0; - virtual void render_scene(Node *root, ProjectionNode *projnode)=0; + virtual void render_scene(Node *root, LensNode *projnode)=0; virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, ProjectionNode *projnode, + Node *subgraph, LensNode *projnode, const AllTransitionsWrapper &net_trans)=0; virtual void render_subgraph(RenderTraverser *traverser, Node *subgraph, @@ -136,7 +136,7 @@ public: RenderBuffer get_render_buffer(int buffer_type); - INLINE ProjectionNode *get_current_projection_node(void) const ; + INLINE LensNode *get_current_camera(void) const ; INLINE const Node* get_current_root_node(void) const; INLINE const DisplayRegion *get_current_display_region(void) const; @@ -222,7 +222,7 @@ protected: // These must be set by render_scene(). Node *_current_root_node; - ProjectionNode *_current_projection_node; + LensNode *_current_camera; CPT(DisplayRegion) _current_display_region; // This is used by wants_normals() diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index bced5ccc61..d81989c566 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,14 +28,13 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -1611,12 +1610,12 @@ report_texmgr_stats() { // Function: DXGraphicsStateGuardian::render_scene // Access: Public, Virtual // Description: Renders an entire scene, from the root node of the -// scene graph, as seen from a particular ProjectionNode +// scene graph, as seen from a particular LensNode // and with a given initial state. This initial state // may be modified during rendering. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -render_scene(Node *root, ProjectionNode *projnode) { +render_scene(Node *root, LensNode *projnode) { #ifdef GSG_VERBOSE _pass_number = 0; dxgsg_cat.debug() @@ -1639,28 +1638,31 @@ render_scene(Node *root, ProjectionNode *projnode) { // Function: DXGraphicsStateGuardian::render_subgraph // Access: Public, Virtual // Description: Renders a subgraph of the scene graph as seen from a -// given projection node, and with a particular initial +// given lens node, and with a particular initial // state. This state may be modified by the render // process. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: render_subgraph(RenderTraverser *traverser, - Node *subgraph, ProjectionNode *projnode, + Node *subgraph, LensNode *projnode, const AllTransitionsWrapper &net_trans) { - ProjectionNode *old_projection_node = _current_projection_node; - _current_projection_node = projnode; + LensNode *old_camera = _current_camera; + _current_camera = projnode; LMatrix4f old_projection_mat = _current_projection_mat; + Lens *lens = projnode->get_lens(); + const LMatrix4f &projection_mat = lens->get_projection_mat(); + // d3d is left-handed coord system - LMatrix4f projection_mat = projnode->get_projection()->get_projection_mat(CS_yup_left); + _current_projection_mat = + LMatrix4f::convert_mat(CS_yup_left, lens->get_coordinate_system()) * + projection_mat; + _projection_mat_stack_count++; #if 0 - dxgsg_cat.spam() << "cur projection matrix: " << projection_mat <<"\n"; + dxgsg_cat.spam() << "cur projection matrix: " << _current_projection_mat <<"\n"; #endif - _current_projection_mat = projection_mat; - _projection_mat_stack_count++; - #ifdef _DEBUG { static bool bPrintedMsg=false; @@ -1686,8 +1688,8 @@ render_subgraph(RenderTraverser *traverser, // We infer the modelview matrix by doing a wrt on the projection // node. LMatrix4f modelview_mat; - get_rel_mat(subgraph, _current_projection_node, modelview_mat); //needs reversal from glgsg, probably due D3D LH coordsys -// get_rel_mat(_current_projection_node, subgraph, modelview_mat); + get_rel_mat(subgraph, _current_camera, modelview_mat); //needs reversal from glgsg, probably due D3D LH coordsys +// get_rel_mat(_current_camera, subgraph, modelview_mat); if (_coordinate_system != CS_yup_left) { // Now we build the coordinate system conversion into the @@ -1704,7 +1706,7 @@ render_subgraph(RenderTraverser *traverser, render_subgraph(traverser, subgraph, sub_trans); - _current_projection_node = old_projection_node; + _current_camera = old_camera; _current_projection_mat = old_projection_mat; _projection_mat_stack_count--; @@ -1720,7 +1722,7 @@ render_subgraph(RenderTraverser *traverser, // Function: DXGraphicsStateGuardian::render_subgraph // Access: Public, Virtual // Description: Renders a subgraph of the scene graph as seen from the -// current projection node, and with a particular +// current lens node, and with a particular // initial state. This state may be modified during the // render process. //////////////////////////////////////////////////////////////////// @@ -2484,8 +2486,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { modelview_mat = ctatt->get_matrix(); // get the camera information - float aspect_ratio; - aspect_ratio = _actual_display_region->get_camera()->get_aspect(); + float aspect_ratio = + get_current_camera()->get_lens()->get_aspect_ratio(); // null the world xform, so sprites are orthog to scrn (but not necessarily camera pnt unless they lie along z-axis) _d3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matIdentity); @@ -4574,7 +4576,7 @@ apply_fog(Fog *fog) { // properties. float fog_start, fog_end; fog->compute_linear_range(fog_start, fog_end, - _current_projection_node, + _current_camera, _coordinate_system); _d3dDevice->SetRenderState( D3DRENDERSTATE_FOGSTART, @@ -4647,7 +4649,7 @@ void DXGraphicsStateGuardian::apply_light( DirectionalLight* light ) { alight.dcvSpecular = *(D3DCOLORVALUE *)(light->get_specular().get_data()); alight.dvDirection = *(D3DVECTOR *) - (get_rel_forward( light, _current_projection_node, CS_yup_left).get_data()); + (get_rel_forward( light, _current_camera, CS_yup_left).get_data()); alight.dvRange = D3DLIGHT_RANGE_MAX; alight.dvFalloff = 1.0f; @@ -4692,12 +4694,12 @@ void DXGraphicsStateGuardian::apply_light( Spotlight* light ) { // Position needs to specify x, y, z, and w // w == 1 implies non-infinite position - LPoint3f pos = get_rel_pos( light, _current_projection_node ); + LPoint3f pos = get_rel_pos( light, _current_camera ); LPoint4f fpos( pos[0], pos[1], pos[2], 1 ); glLightfv( id, GL_POSITION, fpos.get_data() ); glLightfv( id, GL_SPOT_DIRECTION, - get_rel_forward( light, _current_projection_node, + get_rel_forward( light, _current_camera, _coordinate_system ).get_data() ); glLightf( id, GL_SPOT_EXPONENT, light->get_exponent() ); glLightf( id, GL_SPOT_CUTOFF, diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index 49154c9bdc..247b1ec3a9 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.h @@ -137,9 +137,9 @@ public: virtual void prepare_display_region(); virtual void render_frame(); - virtual void render_scene(Node *root, ProjectionNode *projnode); + virtual void render_scene(Node *root, LensNode *projnode); virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, ProjectionNode *projnode, + Node *subgraph, LensNode *projnode, const AllTransitionsWrapper &net_trans); virtual void render_subgraph(RenderTraverser *traverser, Node *subgraph, diff --git a/panda/src/effects/lensFlareNode.cxx b/panda/src/effects/lensFlareNode.cxx index 31db6c749f..6a00bb95f7 100644 --- a/panda/src/effects/lensFlareNode.cxx +++ b/panda/src/effects/lensFlareNode.cxx @@ -28,8 +28,7 @@ #include "transformTransition.h" #include "transparencyTransition.h" #include "renderTraverser.h" -#include "orthoProjection.h" -#include "perspectiveProjection.h" +#include "lens.h" #include "get_rel_pos.h" #include "clockObject.h" #include "allTransitionsWrapper.h" @@ -313,8 +312,8 @@ sub_render(const AllTransitionsWrapper &input_trans, nassertr(_light_node != (Node*) NULL, false); //First we need the light position - ProjectionNode *camera_node = gsg->get_current_projection_node(); - PerspectiveProjection *pp = DCAST(PerspectiveProjection, camera_node->get_projection()); + LensNode *camera_node = gsg->get_current_camera(); + Lens *lens = camera_node->get_lens(); LPoint3f light_pos = get_rel_pos(_light_node, camera_node); @@ -336,7 +335,7 @@ sub_render(const AllTransitionsWrapper &input_trans, //doing everything in camera space, this should merely be the //distance between the camera and the near clipping plane projected //along Y into the screen - LPoint3f center = LPoint3f::origin() + LPoint3f::rfu(0,pp->get_frustum()._fnear,0); + LPoint3f center = LPoint3f::origin() + LPoint3f::rfu(0,lens->get_near(),0); center = center * inv_light_mat * modelview_mat; //Now lets get the vector from the light to the center. @@ -354,7 +353,7 @@ sub_render(const AllTransitionsWrapper &input_trans, dot = (dot < 0.0f) ? -dot : dot; prepare_flares(delta, light_pos, dot); - prepare_blind(dot, pp->get_frustum()._fnear); + prepare_blind(dot, lens->get_near()); render_children(_flare_arcs, input_trans, gsg); render_child(_blind_arc, input_trans, gsg); diff --git a/panda/src/framework/framework.cxx b/panda/src/framework/framework.cxx index 020e848b36..0cb96a0cb2 100644 --- a/panda/src/framework/framework.cxx +++ b/panda/src/framework/framework.cxx @@ -85,7 +85,7 @@ #include "textNode.h" #include "depthTestTransition.h" #include "depthWriteTransition.h" -#include "orthoProjection.h" +#include "orthographicLens.h" #include "transparencyTransition.h" #include "bamReader.h" #include "collisionRay.h" @@ -491,10 +491,9 @@ void setup_framerate(void) { PT(Camera) cam2d = new Camera("framerate_cam"); new RenderRelation(framerate_node, cam2d); cam2d->set_scene(framerate_top); - - Frustumf frustum2d; - frustum2d.make_ortho_2D(); - cam2d->set_projection(OrthoProjection(frustum2d)); + PT(Lens) lens = new OrthographicLens; + lens->set_film_size(2.0); + cam2d->set_lens(lens); // Now create a new layer // eventually this should be done through chanconfig' diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 0bd07f38d7..bfa69571f9 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -26,22 +26,22 @@ #include "directRenderTraverser.h" #include "cullTraverser.h" #include "displayRegion.h" -#include "projectionNode.h" +#include "lensNode.h" #include "camera.h" #include "renderBuffer.h" #include "geom.h" #include "geomIssuer.h" #include "graphicsWindow.h" #include "graphicsChannel.h" -#include "projection.h" +#include "lens.h" #include "get_rel_pos.h" -#include "perspectiveProjection.h" +#include "perspectiveLens.h" #include "ambientLight.h" #include "directionalLight.h" #include "pointLight.h" #include "spotlight.h" #include "GL/glu.h" -#include "projectionNode.h" +#include "lensNode.h" #include "transformTransition.h" #include "colorMatrixTransition.h" #include "alphaTransformTransition.h" @@ -568,12 +568,12 @@ render_frame() { // Function: GLGraphicsStateGuardian::render_scene // Access: Public, Virtual // Description: Renders an entire scene, from the root node of the -// scene graph, as seen from a particular ProjectionNode +// scene graph, as seen from a particular LensNode // and with a given initial state. This initial state // may be modified during rendering. //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -render_scene(Node *root, ProjectionNode *projnode) { +render_scene(Node *root, LensNode *projnode) { #ifdef GSG_VERBOSE _pass_number = 0; glgsg_cat.debug() @@ -596,13 +596,13 @@ render_scene(Node *root, ProjectionNode *projnode) { // Function: GLGraphicsStateGuardian::render_subgraph // Access: Public, Virtual // Description: Renders a subgraph of the scene graph as seen from a -// given projection node, and with a particular initial +// given lens node, and with a particular initial // state. This state may be modified by the render // process. //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: render_subgraph(RenderTraverser *traverser, - Node *subgraph, ProjectionNode *projnode, + Node *subgraph, LensNode *projnode, const AllTransitionsWrapper &net_trans) { // Calling activate() frequently seems to be intolerably expensive // on some platforms. We'll limit ourselves for now to calling it @@ -610,34 +610,37 @@ render_subgraph(RenderTraverser *traverser, // activate(); - ProjectionNode *old_projection_node = _current_projection_node; - _current_projection_node = projnode; + LensNode *old_camera = _current_camera; + _current_camera = projnode; LMatrix4f old_projection_mat = _current_projection_mat; + Lens *lens = projnode->get_lens(); + const LMatrix4f &projection_mat = lens->get_projection_mat(); + // The projection matrix must always be right-handed Y-up, even if // our coordinate system of choice is otherwise, because certain GL // calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of - // a coordinate system. Sigh. In order to implement a Z-up - // coordinate system, we'll store the Z-up conversion in the - // modelview matrix. - LMatrix4f projection_mat = - projnode->get_projection()->get_projection_mat(CS_yup_right); - - _current_projection_mat = projection_mat; + // a coordinate system. Sigh. In order to implement a Z-up (or + // other arbitrary) coordinate system, we'll use a Y-up projection + // matrix, and store the conversion to our coordinate system of + // choice in the modelview matrix. + _current_projection_mat = + LMatrix4f::convert_mat(CS_yup_right, lens->get_coordinate_system()) * + projection_mat; _projection_mat_stack_count++; // We load the projection matrix directly. #ifdef GSG_VERBOSE glgsg_cat.debug() - << "glMatrixMode(GL_PROJECTION): " << projection_mat << endl; + << "glMatrixMode(GL_PROJECTION): " << _current_projection_mat << endl; #endif glMatrixMode(GL_PROJECTION); glLoadMatrixf(_current_projection_mat.get_data()); - // We infer the modelview matrix by doing a wrt on the projection + // We infer the modelview matrix by doing a wrt on the lens // node. LMatrix4f modelview_mat; - get_rel_mat(subgraph, _current_projection_node, modelview_mat); + get_rel_mat(subgraph, _current_camera, modelview_mat); if (_coordinate_system != CS_yup_right) { // Now we build the coordinate system conversion into the @@ -654,7 +657,7 @@ render_subgraph(RenderTraverser *traverser, render_subgraph(traverser, subgraph, sub_trans); - _current_projection_node = old_projection_node; + _current_camera = old_camera; _current_projection_mat = old_projection_mat; _projection_mat_stack_count--; @@ -673,7 +676,7 @@ render_subgraph(RenderTraverser *traverser, // Function: GLGraphicsStateGuardian::render_subgraph // Access: Public, Virtual // Description: Renders a subgraph of the scene graph as seen from the -// current projection node, and with a particular +// current lens node, and with a particular // initial state. This state may be modified during the // render process. //////////////////////////////////////////////////////////////////// @@ -999,40 +1002,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) { modelview_mat = ctatt->get_matrix(); // get the camera information - float aspect_ratio = _actual_display_region->get_camera()->get_aspect(); - - // Note on DO_CHARLES_PROJECTION_MAT - // apparently adjusting the projection as done below is incorrect - // as long as the camera points forward at the view plane, no distortion/warping - // will be apparent, which is what this special projection was supposed to correct - -#ifdef DO_CHARLES_PROJECTION_MAT - // to assure that the scale between the two frustra stays the same - // (if they are different, sprites move at different speeds than the world), - // we have to apply the frustum inverse to the point, then render it in our - // own frustum. Since the z values are identical and 1:1, we only need - // concern ourselves with the x and y mappings, which are conveniently linear. - - float x_frustum_scale, y_frustum_scale; - float recip_x_frustum_scale, recip_y_frustum_scale; - float tnear, tfar, hfov; - - // get the camera information - tnear = _actual_display_region->get_camera()->get_near(); - tfar = _actual_display_region->get_camera()->get_far(); - hfov = _actual_display_region->get_camera()->get_hfov(); - - // extract the left and top bounds of the current camera - x_frustum_scale = tanf(hfov * 0.5f * (3.1415926f / 180.0f)) * tnear; - recip_x_frustum_scale = 1.0f / x_frustum_scale; - y_frustum_scale = x_frustum_scale / aspect_ratio; - recip_y_frustum_scale = 1.0f / y_frustum_scale; - - // load up our own matrices - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0f, 1.0f, -1.0f, 1.0f, tnear, tfar); -#endif + float aspect_ratio = + get_current_camera()->get_lens()->get_aspect_ratio(); // load up our own matrices glMatrixMode(GL_MODELVIEW); @@ -1123,21 +1094,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) { // this mult converts to y-up cameraspace. cameraspace_vert = source_vert * modelview_mat; - -#ifdef DO_CHARLES_PROJECTION_MAT - float x,y,z; - - // do the inverse transform on the cameraspace point. - x = cameraspace_vert[0] ;//* recip_x_frustum_scale; - y = cameraspace_vert[1] ;//* recip_y_frustum_scale; - z = cameraspace_vert[2]; - - // build the final object that will go into the vector. - ws._v.set(x, y, z); -#else // build the final object that will go into the vector. ws._v.set(cameraspace_vert[0],cameraspace_vert[1],cameraspace_vert[2]); -#endif if (color_overall == false) ws._c = geom->get_next_color(ci); @@ -1234,10 +1192,6 @@ draw_sprite(GeomSprite *geom, GeomContext *) { if(alpha && _dithering_enabled) glEnable(GL_DITHER); -#ifdef DO_CHARLES_PROJECTION_MAT - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(_current_projection_mat.get_data()); -#endif report_errors(); _draw_primitive_pcollector.stop(); } @@ -2465,7 +2419,7 @@ apply_fog(Fog *fog) { // object knows how to decode its parameters into camera-relative // properties. float onset, opaque; - fog->compute_linear_range(onset, opaque, _current_projection_node, + fog->compute_linear_range(onset, opaque, _current_camera, _coordinate_system); call_glFogStart(onset); call_glFogEnd(opaque); @@ -2511,7 +2465,7 @@ void GLGraphicsStateGuardian::apply_light( PointLight* light ) // Position needs to specify x, y, z, and w // w == 1 implies non-infinite position - LPoint3f pos = get_rel_pos( light, _current_projection_node ); + LPoint3f pos = get_rel_pos( light, _current_camera ); LPoint4f fpos( pos[0], pos[1], pos[2], 1 ); glLightfv( id, GL_POSITION, fpos.get_data() ); @@ -2570,7 +2524,7 @@ void GLGraphicsStateGuardian::apply_light( DirectionalLight* light ) // Position needs to specify x, y, z, and w // w == 0 implies light is at infinity - LPoint3f dir = get_rel_forward( light, _current_projection_node, + LPoint3f dir = get_rel_forward( light, _current_camera, _coordinate_system ); LPoint4f pos( -dir[0], -dir[1], -dir[2], 0 ); glLightfv( id, GL_POSITION, pos.get_data() ); @@ -2628,12 +2582,12 @@ void GLGraphicsStateGuardian::apply_light( Spotlight* light ) // Position needs to specify x, y, z, and w // w == 1 implies non-infinite position - LPoint3f pos = get_rel_pos( light, _current_projection_node ); + LPoint3f pos = get_rel_pos( light, _current_camera ); LPoint4f fpos( pos[0], pos[1], pos[2], 1 ); glLightfv( id, GL_POSITION, fpos.get_data() ); glLightfv( id, GL_SPOT_DIRECTION, - get_rel_forward( light, _current_projection_node, + get_rel_forward( light, _current_camera, _coordinate_system ).get_data() ); glLightf( id, GL_SPOT_EXPONENT, light->get_exponent() ); glLightf( id, GL_SPOT_CUTOFF, diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index e5ed903114..2831b395af 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -76,9 +76,9 @@ public: virtual void prepare_display_region(); virtual void render_frame(); - virtual void render_scene(Node *root, ProjectionNode *projnode); + virtual void render_scene(Node *root, LensNode *projnode); virtual void render_subgraph(RenderTraverser *traverser, - Node *subgraph, ProjectionNode *projnode, + Node *subgraph, LensNode *projnode, const AllTransitionsWrapper &net_trans); virtual void render_subgraph(RenderTraverser *traverser, Node *subgraph, diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 5338664da6..bf0cf88106 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -4,7 +4,7 @@ #begin lib_target #define TARGET gobj #define LOCAL_LIBS \ - linmath mathutil pnmimage gsgbase graph putil + event linmath mathutil pnmimage gsgbase graph putil #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx @@ -14,9 +14,9 @@ geomQuad.h geomSphere.h geomSprite.I geomSprite.h geomTri.h \ geomTrifan.h geomTristrip.h imageBuffer.I imageBuffer.h \ material.I material.h materialPool.I materialPool.h \ - orthoProjection.I orthoProjection.h perspectiveProjection.I \ - perspectiveProjection.h pixelBuffer.I pixelBuffer.N \ - pixelBuffer.h projection.h \ + orthographicLens.I orthographicLens.h perspectiveLens.I \ + perspectiveLens.h pixelBuffer.I pixelBuffer.N \ + pixelBuffer.h lens.h lens.I \ savedContext.I savedContext.h \ texture.I texture.N texture.h \ textureContext.I textureContext.h \ @@ -27,8 +27,8 @@ geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \ geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \ geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx \ - materialPool.cxx orthoProjection.cxx \ - perspectiveProjection.cxx pixelBuffer.cxx projection.cxx \ + materialPool.cxx orthographicLens.cxx \ + perspectiveLens.cxx pixelBuffer.cxx lens.cxx \ savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx #define INSTALL_HEADERS \ @@ -38,8 +38,9 @@ geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \ geomprimitives.h imageBuffer.I imageBuffer.h material.I material.h \ materialPool.I materialPool.h \ - orthoProjection.I orthoProjection.h perspectiveProjection.I \ - perspectiveProjection.h pixelBuffer.I pixelBuffer.h projection.h \ + orthographicLens.I orthographicLens.h perspectiveLens.I \ + perspectiveLens.h pixelBuffer.I pixelBuffer.h \ + lens.h lens.I \ savedContext.I savedContext.h \ texture.I texture.h \ textureContext.I textureContext.h \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index c605c403c0..0dc437c5ed 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -24,10 +24,10 @@ #include "geomprimitives.h" #include "imageBuffer.h" #include "material.h" -#include "orthoProjection.h" -#include "perspectiveProjection.h" +#include "orthographicLens.h" +#include "perspectiveLens.h" #include "pixelBuffer.h" -#include "projection.h" +#include "lens.h" #include "texture.h" #include @@ -176,10 +176,10 @@ ConfigureFn(config_gobj) { ImageBuffer::init_type(); LOD::init_type(); Material::init_type(); - OrthoProjection::init_type(); - PerspectiveProjection::init_type(); + OrthographicLens::init_type(); + PerspectiveLens::init_type(); PixelBuffer::init_type(); - Projection::init_type(); + Lens::init_type(); Texture::init_type(); dDrawable::init_type(); diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 784e17c6c2..18b261bb1f 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -5,10 +5,10 @@ #include "imageBuffer.cxx" #include "material.cxx" #include "materialPool.cxx" -#include "orthoProjection.cxx" -#include "perspectiveProjection.cxx" +#include "orthographicLens.cxx" +#include "perspectiveLens.cxx" #include "pixelBuffer.cxx" -#include "projection.cxx" +#include "lens.cxx" #include "savedContext.cxx" #include "texture.cxx" #include "textureContext.cxx" diff --git a/panda/src/gobj/lens.I b/panda/src/gobj/lens.I new file mode 100644 index 0000000000..dc2ee92ae7 --- /dev/null +++ b/panda/src/gobj/lens.I @@ -0,0 +1,367 @@ +// Filename: lens.I +// Created by: drose (29Nov01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude +// Access: Published +// Description: Given a 2-d point in the range (-1,1) in both +// dimensions, where (0,0) is the center of the +// lens and (-1,-1) is the lower-left corner, +// compute the corresponding vector in space that maps +// to this point, if such a vector can be determined. +// The vector is returned by indicating the points on +// the near plane and far plane that both map to the +// indicated 2-d point. +// +// Returns true if the vector is defined, or false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool Lens:: +extrude(const LPoint2f &point2d, LPoint3f &near_point, LPoint3f &far_point) const { + return extrude_impl(LPoint3f(point2d[0], point2d[1], 0.0f), + near_point, far_point); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude +// Access: Published +// Description: Given a 2-d point in the range (-1,1) in both +// dimensions, where (0,0) is the center of the +// lens and (-1,-1) is the lower-left corner, +// compute the corresponding vector in space that maps +// to this point, if such a vector can be determined. +// The vector is returned by indicating the points on +// the near plane and far plane that both map to the +// indicated 2-d point. +// +// The z coordinate of the 2-d point is ignored. +// +// Returns true if the vector is defined, or false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool Lens:: +extrude(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const { + return extrude_impl(point2d, near_point, far_point); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::project +// Access: Published +// Description: Given a 3-d point in space, determine the 2-d point +// this maps to, in the range (-1,1) in both dimensions, +// where (0,0) is the center of the lens and +// (-1,-1) is the lower-left corner. +// +// Returns true if the 3-d point is in front of the lens +// and within the viewing frustum (in which case point2d +// is filled in), or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool Lens:: +project(const LPoint3f &point3d, LPoint2f &point2d) const { + LPoint3f result; + if (project_impl(point3d, result)) { + point2d.set(result[0], result[1]); + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::project +// Access: Published +// Description: Given a 3-d point in space, determine the 2-d point +// this maps to, in the range (-1,1) in both dimensions, +// where (0,0) is the center of the lens and +// (-1,-1) is the lower-left corner. +// +// Some lens types also set the z coordinate of the 2-d +// point to a value in the range (-1, 1), where 1 +// represents a point on the near plane, and -1 +// represents a point on the far plane. +// +// Returns true if the 3-d point is in front of the lens +// and within the viewing frustum (in which case point2d +// is filled in), or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool Lens:: +project(const LPoint3f &point3d, LPoint3f &point2d) const { + return project_impl(point3d, point2d); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_change_event +// Access: Published +// Description: Sets the name of the event that will be generated +// whenever any properties of the Lens have +// changed. This can be used to automatically track +// changes to camera fov, etc. in the simulation. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_change_event(const string &event) { + _change_event = event; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_change_event +// Access: Published +// Description: Returns the name of the event that will be generated +// whenever any properties of the Lens have +// changed. +//////////////////////////////////////////////////////////////////// +INLINE const string &Lens:: +get_change_event() const { + return _change_event; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_coordinate_system +// Access: Published +// Description: Returns the coordinate system that all 3-d +// computations are performed within for this +// Lens. Normally, this is CS_default. +//////////////////////////////////////////////////////////////////// +INLINE CoordinateSystem Lens:: +get_coordinate_system() const { + return _cs; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_film_size +// Access: Published +// Description: Sets the size and shape of the "film" within the +// lens. This both establishes the units used by +// calls like set_focal_length(), and establishes the +// aspect ratio of the frame. +// +// In a physical camera, the field of view of a lens is +// determined by the lens' focal length and by the size +// of the film area exposed by the lens. For instance, +// a 35mm camera exposes a rectangle on the film about +// 24mm x 36mm, which means a 50mm lens gives about a +// 40-degree horizontal field of view. +// +// In the virtual camera, you may set the film size to +// any units here, and specify a focal length in the +// same units to simulate the same effect. Or, you may +// ignore this parameter, and specify the field of view +// and aspect ratio of the lens directly. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_film_size(float width, float height) { + set_film_size(LVecBase2f(width, height)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_film_offset +// Access: Published +// Description: Sets the horizontal and vertical offset amounts of +// this Lens. These are both in the same units +// specified in set_film_size(). +// +// This can be used to establish an off-axis lens. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_film_offset(float x, float y) { + set_film_offset(LVecBase2f(x, y)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_film_offset +// Access: Published +// Description: Sets the horizontal and vertical offset amounts of +// this Lens. These are both in the same units +// specified in set_film_size(). +// +// This can be used to establish an off-axis lens. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_film_offset(const LVecBase2f &film_offset) { + _film_offset = film_offset; + adjust_comp_flags(CF_mat, 0); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_film_offset +// Access: Published +// Description: Returns the horizontal and vertical offset amounts of +// this Lens. See set_film_offset(). +//////////////////////////////////////////////////////////////////// +INLINE const LVector2f &Lens:: +get_film_offset() const { + return _film_offset; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_fov +// Access: Published +// Description: Sets the field of view of the lens in both +// dimensions. This establishes both the field of view +// and the aspect ratio of the lens. This is one way to +// specify the field of view of a lens; +// set_focal_length() is another way. +// +// For certain kinds of lenses (like OrthoLens), +// the field of view has no meaning. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_fov(float hfov, float vfov) { + set_fov(LVecBase2f(hfov, vfov)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_hfov +// Access: Published +// Description: Returns the horizontal component of fov only. See +// get_fov(). +//////////////////////////////////////////////////////////////////// +INLINE float Lens:: +get_hfov() const { + return get_fov()[0]; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_vfov +// Access: Published +// Description: Returns the vertical component of fov only. See +// get_fov(). +//////////////////////////////////////////////////////////////////// +INLINE float Lens:: +get_vfov() const { + return get_fov()[1]; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_near +// Access: Published +// Description: Defines the position of the near plane (or cylinder, +// sphere, whatever). Points closer to the lens than +// this may not be rendered. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_near(float near_distance) { + _near_distance = near_distance; + adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv, 0); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_near +// Access: Published +// Description: Returns the position of the near plane (or cylinder, +// sphere, whatever). +//////////////////////////////////////////////////////////////////// +INLINE float Lens:: +get_near() const { + return _near_distance; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_far +// Access: Published +// Description: Defines the position of the far plane (or cylinder, +// sphere, whatever). Points farther from the lens than +// this may not be rendered. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_far(float far_distance) { + _far_distance = far_distance; + adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv, 0); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_far +// Access: Published +// Description: Returns the position of the far plane (or cylinder, +// sphere, whatever). +//////////////////////////////////////////////////////////////////// +INLINE float Lens:: +get_far() const { + return _far_distance; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_near_far +// Access: Published +// Description: Simultaneously changes the near and far planes. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_near_far(float near_distance, float far_distance) { + _near_distance = near_distance; + _far_distance = far_distance; + adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv, 0); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_view_hpr +// Access: Published +// Description: Sets the direction in which the lens is facing. +// Normally, this is down the forward axis (usually the +// Y axis), but it may be rotated. This is only one way +// of specifying the rotation; you may also specify an +// explicit vector in which to look, or you may give a +// complete transformation matrix. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_view_hpr(float h, float p, float r) { + set_view_hpr(LVecBase3f(h, p, r)); +} +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_view_vector +// Access: Published +// Description: Specifies the direction in which the lens is facing +// by giving an axis to look along, and a perpendicular +// (or at least non-parallel) up axis. +// +// See also set_view_hpr(). +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +set_view_vector(float x, float y, float z, float i, float j, float k) { + set_view_vector(LVector3f(x, y, z), LVector3f(i, j, k)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::adjust_user_flags +// Access: Protected +// Description: Clears from _user_flags the bits in the first +// parameter, and sets the bits in the second parameter. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +adjust_user_flags(int clear_flags, int set_flags) { + _user_flags = (_user_flags & ~clear_flags) | set_flags; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::adjust_comp_flags +// Access: Protected +// Description: Clears from _comp_flags the bits in the first +// parameter, and sets the bits in the second parameter. +//////////////////////////////////////////////////////////////////// +INLINE void Lens:: +adjust_comp_flags(int clear_flags, int set_flags) { + _comp_flags = (_comp_flags & ~clear_flags) | set_flags; +} + +EXPCL_PANDA INLINE ostream & +operator << (ostream &out, const Lens &lens) { + lens.output(out); + return out; +} diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx new file mode 100644 index 0000000000..931993f9fd --- /dev/null +++ b/panda/src/gobj/lens.cxx @@ -0,0 +1,1291 @@ +// Filename: lens.cxx +// Created by: drose (18Feb99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "lens.h" +#include "throw_event.h" +#include "compose_matrix.h" +#include "look_at.h" +#include "geomLinestrip.h" +#include "boundingHexahedron.h" +#include "indent.h" +#include "config_gobj.h" + +TypeHandle Lens::_type_handle; + +const float Lens::_default_fov = 40.0f; + +//////////////////////////////////////////////////////////////////// +// Function: Lens::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Lens:: +Lens() { + clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Lens:: +Lens(const Lens ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void Lens:: +operator = (const Lens ©) { + _change_event = copy._change_event; + _cs = copy._cs; + _film_size = copy._film_size; + _film_offset = copy._film_offset; + _focal_length = copy._focal_length; + _fov = copy._fov; + _aspect_ratio = copy._aspect_ratio; + _near_distance = copy._near_distance; + _far_distance = copy._far_distance; + _user_flags = copy._user_flags; + _comp_flags = 0; + + // We don't copy the _geom_coords array. That's unique to each + // Lens. +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_coordinate_system +// Access: Published +// Description: Specifies the coordinate system that all 3-d +// computations are performed within for this +// Lens. Normally, this is CS_default. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_coordinate_system(CoordinateSystem cs) { + _cs = cs; + adjust_comp_flags(CF_mat | CF_view_hpr | CF_view_vector, 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::clear +// Access: Published +// Description: Resets all lens parameters to their initial default +// settings. +//////////////////////////////////////////////////////////////////// +void Lens:: +clear() { + _change_event = ""; + _cs = CS_default; + _film_size.set(1.0f, 1.0f); + _film_offset.set(0.0f, 0.0f); + _focal_length = 1.0f; + _fov.set(_default_fov, _default_fov); + _aspect_ratio = 1.0f; + _near_distance = 1.0f; + _far_distance = 1000.0f; + _view_hpr.set(0.0f, 0.0f, 0.0f); + _view_vector.set(0.0f, 1.0f, 0.0f); + _up_vector.set(0.0f, 0.0f, 1.0f); + _iod_offset = 0.0f; + _user_flags = 0; + _comp_flags = CF_fov; + + // Assign an initial arbitrary sequence to these three. + _film_size_seq = 0; + _focal_length_seq = 1; + _fov_seq = 2; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_film_size +// Access: Published +// Description: Sets the horizontal size of the film without changing +// its shape. The aspect ratio remains unchanged; this +// computes the vertical size of the film to +// automatically maintain the aspect ratio. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_film_size(float width) { + _film_size.set(width, width / get_aspect_ratio()); + + // We can't specify all three of focal length, fov, and film size. + // Throw out the oldest one. + resequence_fov_triad(_film_size_seq, _focal_length_seq, _fov_seq); + + if (_fov_seq == 0) { + // Throw out fov if it's oldest. + adjust_user_flags(UF_hfov | UF_vfov | UF_film_height, + UF_film_width); + } else { + // Otherwise, throw out focal length. + nassertv(_focal_length_seq == 0); + adjust_user_flags(UF_focal_length | UF_film_height, + UF_film_width); + } + adjust_comp_flags(CF_mat | CF_focal_length | CF_fov, + CF_film_size); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_film_size +// Access: Published +// Description: Sets the size and shape of the "film" within the +// lens. This both establishes the units used by +// calls like set_focal_length(), and establishes the +// aspect ratio of the frame. +// +// In a physical camera, the field of view of a lens is +// determined by the lens' focal length and by the size +// of the film area exposed by the lens. For instance, +// a 35mm camera exposes a rectangle on the film about +// 24mm x 36mm, which means a 50mm lens gives about a +// 40-degree horizontal field of view. +// +// In the virtual camera, you may set the film size to +// any units here, and specify a focal length in the +// same units to simulate the same effect. Or, you may +// ignore this parameter, and specify the field of view +// and aspect ratio of the lens directly. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_film_size(const LVecBase2f &film_size) { + _film_size = film_size; + + // We can't specify all three of focal length, fov, and film size. + // Throw out the oldest one. + resequence_fov_triad(_film_size_seq, _focal_length_seq, _fov_seq); + + if (_fov_seq == 0) { + // Throw out fov if it's oldest. + adjust_user_flags(UF_hfov | UF_vfov | UF_aspect_ratio, + UF_film_width | UF_film_height); + } else { + // Otherwise, throw out focal length. + nassertv(_focal_length_seq == 0); + adjust_user_flags(UF_focal_length | UF_vfov | UF_aspect_ratio, + UF_film_width | UF_film_height); + } + adjust_comp_flags(CF_mat | CF_focal_length | CF_fov | CF_aspect_ratio, + CF_film_size); + + // Also, the user has implicitly specified an aspect ratio. Make it + // stick until the user tells us something different. + compute_aspect_ratio(); + adjust_user_flags(0, UF_aspect_ratio); + + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_film_size +// Access: Published +// Description: Returns the horizontal and vertical film size of +// the virtual film. See set_film_size(). +//////////////////////////////////////////////////////////////////// +const LVecBase2f &Lens:: +get_film_size() const { + if ((_comp_flags & CF_film_size) == 0) { + // We pretend this is a const method, even though it may call a + // non-const method to recompute the internal values. We can do + // this because this is just compute-on-demand. + ((Lens *)this)->compute_film_size(); + } + return _film_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_focal_length +// Access: Published +// Description: Sets the focal length of the lens. This may adjust +// the field-of-view correspondingly, and is an +// alternate way to specify field of view. +// +// For certain kinds of lenses (e.g. OrthographicLens), +// the focal length has no meaning. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_focal_length(float focal_length) { + _focal_length = focal_length; + + // We can't specify all three of focal length, fov, and film size. + // Throw out the oldest one. + resequence_fov_triad(_focal_length_seq, _film_size_seq, _fov_seq); + + if (_film_size_seq == 0) { + // Throw out film size if it's oldest. + adjust_user_flags(UF_film_width | UF_film_height, + UF_focal_length); + } else { + // Otherwise, throw out the fov. + nassertv(_fov_seq == 0); + adjust_user_flags(UF_hfov | UF_vfov, + UF_focal_length); + } + + adjust_comp_flags(CF_mat | CF_fov | CF_film_size, + CF_focal_length); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_focal_length +// Access: Published +// Description: Returns the focal length of the lens. This may have +// been set explicitly by a previous call to +// set_focal_length(), or it may be computed based on +// the lens' fov and film_size. For certain kinds of +// lenses, the focal length has no meaning. +//////////////////////////////////////////////////////////////////// +float Lens:: +get_focal_length() const { + if ((_comp_flags & CF_focal_length) == 0) { + ((Lens *)this)->compute_focal_length(); + } + return _focal_length; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_fov +// Access: Published +// Description: Sets the horizontal field of view of the lens without +// changing the aspect ratio. The vertical field of +// view is adjusted to maintain the same aspect ratio. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_fov(float hfov) { + _fov[0] = hfov; + + // We can't specify all three of focal length, fov, and film size. + // Throw out the oldest one. + resequence_fov_triad(_fov_seq, _focal_length_seq, _film_size_seq); + + if (_focal_length_seq == 0) { + // Throw out focal length if it's oldest. + adjust_user_flags(UF_focal_length | UF_vfov, + UF_hfov); + } else { + // Otherwise, throw out film size. + nassertv(_film_size_seq == 0); + adjust_user_flags(UF_film_width | UF_film_height | UF_vfov, + UF_hfov); + } + adjust_comp_flags(CF_mat | CF_focal_length | CF_fov | CF_film_size, + 0); + // We leave CF_fov off of comp_flags, because we will still need to + // recompute the vertical fov. It's not exactly the same as hfov * + // get_aspect_ratio(). + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_fov +// Access: Published +// Description: Sets the field of view of the lens in both +// dimensions. This establishes both the field of view +// and the aspect ratio of the lens. This is one way to +// specify the field of view of a lens; +// set_focal_length() is another way. +// +// For certain kinds of lenses (like OrthographicLens), +// the field of view has no meaning. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_fov(const LVecBase2f &fov) { + _fov = fov; + + // We can't specify all three of focal length, fov, and film size. + // Throw out the oldest one. + resequence_fov_triad(_fov_seq, _focal_length_seq, _film_size_seq); + + if (_focal_length_seq == 0) { + // Throw out focal length if it's oldest. + adjust_user_flags(UF_focal_length | UF_film_height | UF_aspect_ratio, + UF_hfov | UF_vfov); + } else { + // Otherwise, throw out film size. + nassertv(_film_size_seq == 0); + adjust_user_flags(UF_film_width | UF_film_height | UF_aspect_ratio, + UF_hfov | UF_vfov); + } + adjust_comp_flags(CF_mat | CF_focal_length | CF_film_size | CF_aspect_ratio, + CF_fov); + + // Also, the user has implicitly specified an aspect ratio. Make it + // stick until the user tells us something different. + compute_aspect_ratio(); + adjust_user_flags(0, UF_aspect_ratio); + + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_fov +// Access: Published +// Description: Returns the horizontal and vertical film size of +// the virtual film. See set_fov(). +//////////////////////////////////////////////////////////////////// +const LVecBase2f &Lens:: +get_fov() const { + if ((_comp_flags & CF_fov) == 0) { + ((Lens *)this)->compute_fov(); + } + return _fov; +} + + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_aspect_ratio +// Access: Published +// Description: Sets the aspect ratio of the lens. This is the ratio +// of the height to the width of the generated image. +// Setting this overrides the two-parameter fov or film +// size setting. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_aspect_ratio(float aspect_ratio) { + _aspect_ratio = aspect_ratio; + adjust_user_flags(UF_film_height | UF_vfov, + UF_aspect_ratio); + adjust_comp_flags(CF_mat | CF_film_size | CF_fov, + CF_aspect_ratio); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_aspect_ratio +// Access: Published +// Description: Returns the aspect ratio of the Lens. This is +// determined based on the indicated film size; see +// set_film_size(). +//////////////////////////////////////////////////////////////////// +float Lens:: +get_aspect_ratio() const { + if ((_comp_flags & CF_aspect_ratio) == 0) { + ((Lens *)this)->compute_aspect_ratio(); + } + return _aspect_ratio; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_view_hpr +// Access: Published +// Description: Sets the direction in which the lens is facing. +// Normally, this is down the forward axis (usually the +// Y axis), but it may be rotated. This is only one way +// of specifying the rotation; you may also specify an +// explicit vector in which to look, or you may give a +// complete transformation matrix. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_view_hpr(const LVecBase3f &view_hpr) { + _view_hpr = view_hpr; + adjust_user_flags(UF_view_vector | UF_view_mat, + UF_view_hpr); + adjust_comp_flags(CF_mat | CF_view_vector | CF_iod_offset, + CF_view_hpr); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_view_hpr +// Access: Published +// Description: Returns the direction in which the lens is facing. +//////////////////////////////////////////////////////////////////// +const LVecBase3f &Lens:: +get_view_hpr() const { + if ((_comp_flags & CF_view_hpr) == 0) { + ((Lens *)this)->compute_view_hpr(); + } + return _view_hpr; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_view_vector +// Access: Published +// Description: Specifies the direction in which the lens is facing +// by giving an axis to look along, and a perpendicular +// (or at least non-parallel) up axis. +// +// See also set_view_hpr(). +//////////////////////////////////////////////////////////////////// +void Lens:: +set_view_vector(const LVector3f &view_vector, const LVector3f &up_vector) { + _view_vector = view_vector; + _up_vector = up_vector; + adjust_user_flags(UF_view_hpr | UF_view_mat, + UF_view_vector); + adjust_comp_flags(CF_mat | CF_view_hpr | CF_iod_offset, + CF_view_vector); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_view_vector +// Access: Published +// Description: Returns the axis along which the lens is facing. +//////////////////////////////////////////////////////////////////// +const LVector3f &Lens:: +get_view_vector() const { + if ((_comp_flags & CF_view_vector) == 0) { + ((Lens *)this)->compute_view_vector(); + } + return _view_vector; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_up_vector +// Access: Published +// Description: Returns the axis perpendicular to the camera's view +// vector that indicates the "up" direction. +//////////////////////////////////////////////////////////////////// +const LVector3f &Lens:: +get_up_vector() const { + if ((_comp_flags & CF_view_vector) == 0) { + ((Lens *)this)->compute_view_vector(); + } + return _up_vector; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_iod_offset +// Access: Published +// Description: Sets the amount by which the lens is shifted to the +// right, perpendicular to its view vector and up +// vector. This is normally used to shift one or both +// lens of a stereo camera to generate parallax. You +// can also simply set a complete transformation matrix +// (via set_view_mat()) that includes an arbitrary +// translation. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_iod_offset(float iod_offset) { + _iod_offset = iod_offset; + adjust_user_flags(UF_view_mat, + UF_iod_offset); + adjust_comp_flags(CF_mat | CF_view_hpr | CF_view_vector, + CF_iod_offset); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_iod_offset +// Access: Published +// Description: Returns the aspect ratio of the Lens. This is +// determined based on the indicated film size; see +// set_film_size(). +//////////////////////////////////////////////////////////////////// +float Lens:: +get_iod_offset() const { + if ((_comp_flags & CF_iod_offset) == 0) { + ((Lens *)this)->compute_iod_offset(); + } + return _iod_offset; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::set_view_mat +// Access: Published +// Description: Sets an arbitrary transformation on the lens. This +// replaces the individual transformation components +// like set_view_hpr() or set_iod_offset(). +// +// Setting a transformation here will have a slightly +// different effect than putting one on the LensNode +// that contains this lens. In particular, lighting and +// other effects computations will still be performed on +// the lens in its untransformed (facing forward) +// position, but the actual projection matrix will be +// transformed by this matrix. +//////////////////////////////////////////////////////////////////// +void Lens:: +set_view_mat(const LMatrix4f &view_mat) { + _lens_mat = view_mat; + adjust_user_flags(UF_view_vector | UF_view_hpr | UF_iod_offset, + UF_view_mat); + adjust_comp_flags(CF_lens_mat_inv | CF_view_hpr | CF_view_vector | CF_iod_offset, + CF_lens_mat); + throw_change_event(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_view_mat +// Access: Published +// Description: Returns the direction in which the lens is facing. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_view_mat() const { + if ((_comp_flags & CF_lens_mat) == 0) { + ((Lens *)this)->compute_lens_mat(); + } + return _lens_mat; +} + + +//////////////////////////////////////////////////////////////////// +// Function: Lens::recompute_all +// Access: Published +// Description: Forces all internal parameters of the Lens to be +// recomputed. Normally, this should never need to be +// called; it is provided only to assist in debugging. +//////////////////////////////////////////////////////////////////// +void Lens:: +recompute_all() { + _comp_flags = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::is_linear +// Access: Published, Virtual +// Description: Returns true if the lens represents a linear +// projection (e.g. PerspectiveLens, OrthographicLens), +// and therefore there is a valid matrix returned by +// get_projection_mat(), or false otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +is_linear() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::make_geometry +// Access: Published, Virtual +// Description: Allocates and returns a new Geom that can be rendered +// to show a visible representation of the frustum used +// for this kind of lens, if it makes sense to do +// so. If a visible representation cannot be created, +// returns NULL. +//////////////////////////////////////////////////////////////////// +PT(Geom) Lens:: +make_geometry() { + // The default behavior for make_geometry() will be to draw a + // hexahedron around the eight vertices of the frustum. If the lens + // is non-linear, the hexahedron will be curved; in this case, we'll + // subdivide the lines into several segments to get an approximation + // of the curve. + + // First, define all the points we'll use in this Geom. That's one + // point at each corner of the near and far planes (and possibly + // more points along the edges). + int num_segments = define_geom_coords(); + if (num_segments == 0) { + // Can't do a frustum. + _geom_coords.clear(); + return (Geom *)NULL; + } + + // Now string together the line segments. + PTA_ushort vindex; + PTA_int lengths; + PTA_Colorf colors; + + int num_points = num_segments * 4; + + // Draw a frame around the near plane. + int i; + for (i = 0; i < num_points; i++) { + vindex.push_back(i * num_segments * 2); + } + vindex.push_back(0); + lengths.push_back(num_points + 1); + + // Draw a frame around the far plane. + for (i = 0; i < num_points; i++) { + vindex.push_back(i * num_segments * 2 + 1); + } + vindex.push_back(1); + lengths.push_back(num_points + 1); + + // Draw connecting lines at the corners. + vindex.push_back(0); + vindex.push_back(1); + lengths.push_back(2); + + vindex.push_back(num_segments * 2 + 0); + vindex.push_back(num_segments * 2+ 1); + lengths.push_back(2); + + vindex.push_back(num_segments * 4 + 0); + vindex.push_back(num_segments * 4 + 1); + lengths.push_back(2); + + vindex.push_back(num_segments * 6 + 0); + vindex.push_back(num_segments * 6 + 1); + lengths.push_back(2); + + // And one more line for the viewing axis. + vindex.push_back(num_segments * 8 + 0); + vindex.push_back(num_segments * 8 + 1); + lengths.push_back(2); + + // We just specify overall color. + colors.push_back(Colorf(1.0, 1.0, 1.0, 1.0)); + + GeomLinestrip *gline = new GeomLinestrip; + gline->set_coords(_geom_coords, vindex); + gline->set_colors(colors, G_OVERALL); + gline->set_lengths(lengths); + gline->set_num_prims(lengths.size()); + + return gline; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::make_bounds +// Access: Published, Virtual +// Description: Allocates and returns a new BoundingVolume that +// encloses the frustum used for this kind of +// lens, if possible. If a suitable bounding +// volume cannot be created, returns NULL. +//////////////////////////////////////////////////////////////////// +PT(BoundingVolume) Lens:: +make_bounds() const { + // The default bounding volume is a hexahedron based on the eight + // corners of the frustum. + LPoint3f fll, flr, ful, fur; + LPoint3f nll, nlr, nul, nur; + + // Upper left. + if (!extrude(LPoint2f(-1.0, 1.0), nul, ful)) { + return (BoundingVolume *)NULL; + } + + // Upper right. + if (!extrude(LPoint2f(1.0, 1.0), nur, fur)) { + return (BoundingVolume *)NULL; + } + + // Lower right. + if (!extrude(LPoint2f(1.0, -1.0), nlr, flr)) { + return (BoundingVolume *)NULL; + } + + // Lower left. + if (!extrude(LPoint2f(-1.0, -1.0), nll, fll)) { + return (BoundingVolume *)NULL; + } + + return new BoundingHexahedron(fll, flr, fur, ful, nll, nlr, nur, nul); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_projection_mat +// Access: Published +// Description: Returns the complete transformation matrix from a 3-d +// point in space to a point on the film, if such a +// matrix exists, or the identity matrix if the lens is +// nonlinear. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_projection_mat() const { + if ((_comp_flags & CF_projection_mat) == 0) { + ((Lens *)this)->compute_projection_mat(); + } + return _projection_mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_projection_mat_inv +// Access: Public +// Description: Returns the matrix that transforms from a 2-d point +// on the film to a 3-d vector in space, if such a +// matrix exists. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_projection_mat_inv() const { + if ((_comp_flags & CF_projection_mat_inv) == 0) { + Lens *non_const = (Lens *)this; + const LMatrix4f &projection_mat = get_projection_mat(); + non_const->_projection_mat_inv.invert_from(projection_mat); + non_const->adjust_comp_flags(0, CF_projection_mat_inv); + } + return _projection_mat_inv; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void Lens:: +output(ostream &out) const { + out << get_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void Lens:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << get_type() << " fov = " << get_fov() << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::throw_change_event +// Access: Protected +// Description: Throws the event associated with changing properties +// on this Lens, if any. +//////////////////////////////////////////////////////////////////// +void Lens:: +throw_change_event() { + if (!_change_event.empty()) { + throw_event(_change_event); + } + + // Also update the _geom_coords, if it is in use. + if (!_geom_coords.is_null()) { + if (_geom_coords.get_ref_count() == 1) { + // No one's using the array any more (other than us), so release + // it. + _geom_coords.clear(); + } else { + // Someone else still has a handle to the array, so recompute + // it. + define_geom_coords(); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_film_mat +// Access: Protected +// Description: Returns the matrix that transforms from a point +// behind the lens to a point on the film. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_film_mat() const { + if ((_comp_flags & CF_film_mat) == 0) { + ((Lens *)this)->compute_film_mat(); + } + return _film_mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_film_mat_inv +// Access: Protected +// Description: Returns the matrix that transforms from a point on +// the film to a point behind the lens. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_film_mat_inv() const { + if ((_comp_flags & CF_film_mat_inv) == 0) { + Lens *non_const = (Lens *)this; + const LMatrix4f &film_mat = get_film_mat(); + non_const->_film_mat_inv.invert_from(film_mat); + non_const->adjust_comp_flags(0, CF_film_mat_inv); + } + return _film_mat_inv; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_lens_mat +// Access: Protected +// Description: Returns the matrix that transforms from a point +// in front of the lens to a point in space. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_lens_mat() const { + if ((_comp_flags & CF_lens_mat) == 0) { + ((Lens *)this)->compute_lens_mat(); + } + return _lens_mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::get_lens_mat_inv +// Access: Protected +// Description: Returns the matrix that transforms from a point in +// space to a point in front of the lens. +//////////////////////////////////////////////////////////////////// +const LMatrix4f &Lens:: +get_lens_mat_inv() const { + if ((_comp_flags & CF_lens_mat_inv) == 0) { + Lens *non_const = (Lens *)this; + const LMatrix4f &lens_mat = get_lens_mat(); + non_const->_lens_mat_inv.invert_from(lens_mat); + non_const->adjust_comp_flags(0, CF_lens_mat_inv); + } + return _lens_mat_inv; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude +// Access: Protected, Virtual +// Description: Given a 2-d point in the range (-1,1) in both +// dimensions, where (0,0) is the center of the +// lens and (-1,-1) is the lower-left corner, +// compute the corresponding vector in space that maps +// to this point, if such a vector can be determined. +// The vector is returned by indicating the points on +// the near plane and far plane that both map to the +// indicated 2-d point. +// +// The z coordinate of the 2-d point is ignored. +// +// Returns true if the vector is defined, or false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const { + const LMatrix4f &projection_mat_inv = get_projection_mat_inv(); + { + LVecBase4f full(point2d[0], point2d[1], -1.0f, 1.0f); + full = projection_mat_inv.xform(full); + if (full[3] == 0.0f) { + return false; + } + near_point.set(full[0] / full[3], full[1] / full[3], full[2] / full[3]); + } + { + LVecBase4f full(point2d[0], point2d[1], 1.0f, 1.0f); + full = projection_mat_inv.xform(full); + if (full[3] == 0.0f) { + return false; + } + far_point.set(full[0] / full[3], full[1] / full[3], full[2] / full[3]); + } + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::project_impl +// Access: Protected, Virtual +// Description: Given a 3-d point in space, determine the 2-d point +// this maps to, in the range (-1,1) in both dimensions, +// where (0,0) is the center of the lens and +// (-1,-1) is the lower-left corner. +// +// Some lens types also set the z coordinate of the 2-d +// point to a value in the range (-1, 1), where 1 +// represents a point on the near plane, and -1 +// represents a point on the far plane. +// +// Returns true if the 3-d point is in front of the lens +// and within the viewing frustum (in which case point2d +// is filled in), or false otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { + const LMatrix4f &projection_mat = get_projection_mat(); + LVecBase4f full(point3d[0], point3d[1], point3d[2], 1.0f); + full = projection_mat.xform(full); + if (full[3] == 0.0f) { + return false; + } + point2d.set(full[0] / full[3], full[1] / full[3], full[2] / full[3]); + return point2d[0] >= -1.0f && point2d[0] <= 1.0f && + point2d[1] >= -1.0f && point2d[1] <= 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_film_size +// Access: Protected, Virtual +// Description: Computes the size and shape of the film behind the +// camera, based on the aspect ratio and fov. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_film_size() { + if ((_user_flags & UF_film_width) == 0) { + if ((_user_flags & (UF_hfov | UF_focal_length)) == (UF_hfov | UF_focal_length)) { + _film_size[0] = fov_to_film(_fov[0], _focal_length, true); + } else { + _film_size[0] = 1.0f; + } + } + + if ((_user_flags & UF_film_height) == 0) { + if ((_user_flags & (UF_vfov | UF_focal_length)) == (UF_vfov | UF_focal_length)) { + _film_size[1] = fov_to_film(_fov[1], _focal_length, false); + + } else if ((_user_flags & (UF_hfov | UF_vfov)) == (UF_hfov | UF_vfov)) { + // If we don't have a focal length, but we have an explicit vfov + // and hfov, we can infer the focal length is whatever makes the + // film width, above, be what it is. + if ((_comp_flags & CF_focal_length) == 0) { + _focal_length = fov_to_focal_length(_fov[0], _film_size[0], true); + adjust_comp_flags(0, CF_focal_length); + } + _film_size[1] = fov_to_film(_fov[1], _focal_length, false); + + } else if ((_user_flags & UF_aspect_ratio) != 0) { + _film_size[1] = _film_size[0] / _aspect_ratio; + + } else { + // Default is an aspect ratio of 1. + _film_size[1] = _film_size[0]; + } + } + + adjust_comp_flags(0, CF_film_size); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_focal_length +// Access: Protected, Virtual +// Description: Computes the focal length of the lens, based on the +// fov and film size. This is based on the horizontal +// dimension. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_focal_length() { + if ((_user_flags & UF_focal_length) == 0) { + const LVecBase2f &film_size = get_film_size(); + const LVecBase2f &fov = get_fov(); + _focal_length = fov_to_focal_length(fov[0], film_size[0], true); + } + + adjust_comp_flags(0, CF_focal_length); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_fov +// Access: Protected, Virtual +// Description: Computes the field of view of the lens, based on the +// film size and focal length. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_fov() { + const LVecBase2f &film_size = get_film_size(); + + if ((_user_flags & UF_hfov) == 0) { + if ((_user_flags & UF_focal_length) != 0) { + _fov[0] = film_to_fov(film_size[0], _focal_length, true); + } else { + _fov[0] = _default_fov; + } + } + + if ((_user_flags & UF_vfov) == 0) { + if ((_user_flags & UF_focal_length) == 0 && + (_comp_flags & CF_focal_length) == 0) { + // If we don't have an explicit focal length, we can infer it + // from the above. + _focal_length = fov_to_focal_length(_fov[0], film_size[0], true); + adjust_comp_flags(0, CF_focal_length); + } + _fov[1] = film_to_fov(film_size[1], _focal_length, false); + } + + adjust_comp_flags(0, CF_fov); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_aspect_ratio +// Access: Protected, Virtual +// Description: Computes the aspect ratio of the film rectangle, as a +// ratio of width to height. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_aspect_ratio() { + if ((_user_flags & UF_aspect_ratio) == 0) { + const LVecBase2f &film_size = get_film_size(); + if (film_size[1] == 0.0f) { + _aspect_ratio = 1.0f; + } else { + _aspect_ratio = film_size[0] / film_size[1]; + } + adjust_comp_flags(0, CF_aspect_ratio); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_view_hpr +// Access: Protected, Virtual +// Description: Computes the Euler angles representing the lens' +// rotation. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_view_hpr() { + if ((_user_flags & UF_view_hpr) == 0) { + const LMatrix4f &view_mat = get_view_mat(); + LVecBase3f scale, translate; + decompose_matrix(view_mat, scale, _view_hpr, translate, _cs); + } + adjust_comp_flags(0, CF_view_hpr); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_view_vector +// Access: Protected, Virtual +// Description: Computes the view vector and up vector for the lens. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_view_vector() { + if ((_user_flags & UF_view_vector) == 0) { + const LMatrix4f &view_mat = get_view_mat(); + _view_vector = LVector3f::forward(_cs) * view_mat; + _up_vector = LVector3f::up(_cs) * view_mat; + } + adjust_comp_flags(0, CF_view_vector); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_iod_offset +// Access: Protected, Virtual +// Description: Computes the IOD offset: the translation along the +// "right" axis. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_iod_offset() { + if ((_user_flags & UF_iod_offset) == 0) { + const LMatrix4f &lens_mat_inv = get_lens_mat_inv(); + LVector3f translate; + lens_mat_inv.get_row3(translate, 3); + _iod_offset = -translate.dot(LVector3f::right(_cs)); + } + adjust_comp_flags(0, CF_iod_offset); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_projection_mat +// Access: Protected, Virtual +// Description: Computes the complete transformation matrix from 3-d +// point to 2-d point, if the lens is linear. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_projection_mat() { + _projection_mat = LMatrix4f::ident_mat(); + _projection_mat_inv = _projection_mat; + adjust_comp_flags(0, CF_projection_mat | CF_projection_mat_inv); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_film_mat +// Access: Protected, Virtual +// Description: Computes the matrix that transforms from a point +// behind the lens to a point on the film. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_film_mat() { + // The lens will return a point in the range [-film_size/2, + // film_size/2] in each dimension. Convert this to [-1, 1], and + // also apply the offset. + const LVecBase2f &film_size = get_film_size(); + const LVector2f &film_offset = get_film_offset(); + _film_mat = + LMatrix4f::translate_mat(-film_offset[0], -film_offset[1], 0.0) * + LMatrix4f::scale_mat(2.0f / film_size[0], 2.0f / film_size[1], 1.0); + adjust_comp_flags(CF_film_mat_inv, + CF_film_mat); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::compute_lens_mat +// Access: Protected, Virtual +// Description: Computes the matrix that transforms from a point +// in front of the lens to a point in space. +//////////////////////////////////////////////////////////////////// +void Lens:: +compute_lens_mat() { + if ((_user_flags & UF_view_mat) == 0) { + if ((_user_flags & UF_view_hpr) != 0) { + compose_matrix(_lens_mat, + LVecBase3f(1.0f, 1.0f, 1.0f), _view_hpr, + LVecBase3f(0.0f, 0.0f, 0.0f), _cs); + + } else if ((_user_flags & UF_view_vector) != 0) { + look_at(_lens_mat, _view_vector, _up_vector, _cs); + + } else { + _lens_mat = LMatrix4f::ident_mat(); + } + + if ((_user_flags & UF_iod_offset) != 0) { + LVector3f iod_vector = _iod_offset * LVector3f::right(_cs); + _lens_mat = LMatrix4f::translate_mat(iod_vector) * _lens_mat; + } + } + adjust_comp_flags(CF_lens_mat_inv, + CF_lens_mat); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::fov_to_film +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a focal length, +// compute the corresponding width (or height) on the +// film. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float Lens:: +fov_to_film(float, float, bool) const { + return 1.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::fov_to_focal_length +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a width (or +// height) on the film, compute the focal length of the +// lens. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float Lens:: +fov_to_focal_length(float, float, bool) const { + return 1.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::film_to_fov +// Access: Protected, Virtual +// Description: Given a width (or height) on the film and a focal +// length, compute the field of view in degrees. If +// horiz is true, this is in the horizontal direction; +// otherwise, it is in the vertical direction (some +// lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float Lens:: +film_to_fov(float, float, bool) const { + return _default_fov; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::resequence_fov_triad +// Access: Private, Static +// Description: Called whenever the user changes one of the three FOV +// parameters: fov, focal length, or film size. This +// rearranges the three sequence numbers so the newest +// parameter has value 2, and the older parameters are +// kept in sequence order. +// +// This is used to determine which two parameters of the +// three are the most recently changed, and conversely, +// which one the user has *not* changed recently. It is +// this third value which should be discarded. +//////////////////////////////////////////////////////////////////// +void Lens:: +resequence_fov_triad(char &newest, char &older_a, char &older_b) { + switch (newest) { + case 0: + newest = 2; + older_a--; + older_b--; + nassertv(older_a + older_b == 1); + return; + + case 1: + newest = 2; + if (older_a == 2) { + nassertv(older_b == 0); + older_a = 1; + } else { + nassertv(older_a == 0 && older_b == 2); + older_b = 1; + } + return; + + case 2: + nassertv(older_a + older_b == 1); + return; + + default: + gobj_cat.error() + << "Invalid fov sequence numbers in lens: " << newest << ", " << older_a + << ", " << older_b << "\n"; + nassertv(false); + return; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::define_geom_coords +// Access: Private +// Description: Adjusts (or defines for the first time) all the +// vertices in the _geom_coords array to match the +// properties of the lens. This will update the visual +// representation of the lens's frustum to match the +// changing parameters. Returns the number of line +// segments per edge. +//////////////////////////////////////////////////////////////////// +int Lens:: +define_geom_coords() { + int num_segments = 1; + if (!is_linear()) { + num_segments = 10; + } + + PTA_Vertexf coords; + LPoint3f near_point, far_point; + for (int si = 0; si < num_segments; si++) { + float t = 2.0f * (float)si / (float)num_segments; + + // Upper left, top edge. + LPoint2f p1(-1.0f + t, 1.0); + if (!extrude(p1, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + coords.push_back(near_point); + coords.push_back(far_point); + + // Upper right, right edge. + LPoint2f p2(1.0, 1.0f - t); + if (!extrude(p2, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + coords.push_back(near_point); + coords.push_back(far_point); + + // Lower right, bottom edge. + LPoint2f p3(1.0f - t, -1.0); + if (!extrude(p3, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + coords.push_back(near_point); + coords.push_back(far_point); + + // Lower left, left edge. + LPoint2f p4(-1.0, -1.0f + t); + if (!extrude(p4, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + coords.push_back(near_point); + coords.push_back(far_point); + } + + // Finally, push one more pair for the viewing axis. + LPoint3f near_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _near_distance; + LPoint3f far_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _far_distance; + const LMatrix4f &lens_mat = get_lens_mat(); + near_axis = near_axis * lens_mat; + far_axis = far_axis * lens_mat; + coords.push_back(near_axis); + coords.push_back(far_axis); + + if (_geom_coords.is_null()) { + // If the previous array is NULL, simply assign the pointer. + _geom_coords = coords; + } else { + // Otherwise, swap out the vectors within the array so other + // objects that share the PTA will get the new data. + _geom_coords.v().swap(coords.v()); + } + + return num_segments; +} diff --git a/panda/src/gobj/lens.h b/panda/src/gobj/lens.h new file mode 100644 index 0000000000..199b2e52dc --- /dev/null +++ b/panda/src/gobj/lens.h @@ -0,0 +1,242 @@ +// Filename: lens.h +// Created by: drose (18Feb99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef LENS_H +#define LENS_H + +#include "pandabase.h" + +#include "typedReferenceCount.h" +#include "luse.h" +#include "geom.h" + +class BoundingVolume; + +//////////////////////////////////////////////////////////////////// +// Class : Lens +// Description : A base class for any number of different kinds of +// lenses, linear and otherwise. Presently, this +// includes perspective and orthographic lenses. +// +// A Lens object is the main part of a Camera node +// (defined in sgraph), which defines the fundamental +// interface to point-of-view for rendering. Lenses are +// also used in other contexts, however; for instance, a +// Spotlight is also defined using a lens. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA Lens : public TypedReferenceCount { +public: + Lens(); + Lens(const Lens ©); + void operator = (const Lens ©); + +PUBLISHED: + virtual PT(Lens) make_copy() const=0; + + INLINE bool extrude(const LPoint2f &point2d, + LPoint3f &near_point, LPoint3f &far_point) const; + INLINE bool extrude(const LPoint3f &point2d, + LPoint3f &near_point, LPoint3f &far_point) const; + INLINE bool project(const LPoint3f &point3d, LPoint3f &point2d) const; + INLINE bool project(const LPoint3f &point3d, LPoint2f &point2d) const; + + INLINE void set_change_event(const string &event); + INLINE const string &get_change_event() const; + + void set_coordinate_system(CoordinateSystem cs); + INLINE CoordinateSystem get_coordinate_system() const; + + void clear(); + + void set_film_size(float width); + INLINE void set_film_size(float width, float height); + void set_film_size(const LVecBase2f &film_size); + const LVecBase2f &get_film_size() const; + + INLINE void set_film_offset(float x, float y); + INLINE void set_film_offset(const LVecBase2f &film_offset); + INLINE const LVector2f &get_film_offset() const; + + void set_focal_length(float focal_length); + float get_focal_length() const; + + void set_fov(float fov); + INLINE void set_fov(float hfov, float vfov); + void set_fov(const LVecBase2f &fov); + const LVecBase2f &get_fov() const; + INLINE float get_hfov() const; + INLINE float get_vfov() const; + + void set_aspect_ratio(float aspect_ratio); + float get_aspect_ratio() const; + + INLINE void set_near(float near_distance); + INLINE float get_near() const; + INLINE void set_far(float far_distance); + INLINE float get_far() const; + INLINE void set_near_far(float near_distance, float far_distance); + + INLINE void set_view_hpr(float h, float p, float r); + void set_view_hpr(const LVecBase3f &view_hpr); + const LVecBase3f &get_view_hpr() const; + INLINE void set_view_vector(float x, float y, float z, float i, float j, float k); + void set_view_vector(const LVector3f &view_vector, const LVector3f &up_vector); + const LVector3f &get_view_vector() const; + const LVector3f &get_up_vector() const; + void set_iod_offset(float offset); + float get_iod_offset() const; + + void set_view_mat(const LMatrix4f &view_mat); + const LMatrix4f &get_view_mat() const; + + void recompute_all(); + + virtual bool is_linear() const; + virtual PT(Geom) make_geometry(); + + virtual PT(BoundingVolume) make_bounds() const; + + const LMatrix4f &get_projection_mat() const; + const LMatrix4f &get_projection_mat_inv() const; + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + INLINE void adjust_user_flags(int clear_flags, int set_flags); + INLINE void adjust_comp_flags(int clear_flags, int set_flags); + + void throw_change_event(); + + const LMatrix4f &get_film_mat() const; + const LMatrix4f &get_film_mat_inv() const; + + const LMatrix4f &get_lens_mat() const; + const LMatrix4f &get_lens_mat_inv() const; + + virtual bool extrude_impl(const LPoint3f &point2d, + LPoint3f &near_point, LPoint3f &far_point) const; + virtual bool project_impl(const LPoint3f &point3d, LPoint3f &point2d) const; + + virtual void compute_film_size(); + virtual void compute_focal_length(); + virtual void compute_fov(); + virtual void compute_aspect_ratio(); + virtual void compute_view_hpr(); + virtual void compute_view_vector(); + virtual void compute_iod_offset(); + virtual void compute_projection_mat(); + virtual void compute_film_mat(); + virtual void compute_lens_mat(); + + virtual float fov_to_film(float fov, float focal_length, bool horiz) const; + virtual float fov_to_focal_length(float fov, float film_size, bool horiz) const; + virtual float film_to_fov(float film_size, float focal_length, bool horiz) const; + +private: + static void resequence_fov_triad(char &newest, char &older_a, char &older_b); + int define_geom_coords(); + +protected: + string _change_event; + CoordinateSystem _cs; + + LVecBase2f _film_size; + LVector2f _film_offset; + float _focal_length; + LVecBase2f _fov; + float _aspect_ratio; + float _near_distance, _far_distance; + + LVecBase3f _view_hpr; + LVector3f _view_vector, _up_vector; + float _iod_offset; + + LMatrix4f _film_mat, _film_mat_inv; + LMatrix4f _lens_mat, _lens_mat_inv; + LMatrix4f _projection_mat, _projection_mat_inv; + + enum UserFlags { + // Parameters the user may have explicitly specified. + UF_film_width = 0x0001, + UF_film_height = 0x0002, + UF_focal_length = 0x0004, + UF_hfov = 0x0008, + UF_vfov = 0x0010, + UF_aspect_ratio = 0x0020, + UF_view_hpr = 0x0040, + UF_view_vector = 0x0080, + UF_iod_offset = 0x0100, + UF_view_mat = 0x0200, + }; + + enum CompFlags { + // Values that may need to be recomputed. + CF_film_mat = 0x0001, + CF_film_mat_inv = 0x0002, + CF_lens_mat = 0x0004, + CF_lens_mat_inv = 0x0008, + CF_projection_mat = 0x0010, + CF_projection_mat_inv = 0x0020, + CF_mat = 0x003f, // all of the above. + + CF_focal_length = 0x0040, + CF_fov = 0x0080, + CF_film_size = 0x0100, + CF_aspect_ratio = 0x0200, + CF_view_hpr = 0x0400, + CF_view_vector = 0x0800, + CF_iod_offset = 0x1000, + }; + short _user_flags; + short _comp_flags; + + // The user may only specify two of these three parameters. + // Specifying the third parameter wipes out the first one specified. + // We therefore need to remember the order in which the user has + // specified these three parameters. A bit of a mess. + char _focal_length_seq, _fov_seq, _film_size_seq; + + PTA_Vertexf _geom_coords; + + static const float _default_fov; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "Lens", + TypedReferenceCount::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +EXPCL_PANDA INLINE ostream &operator << (ostream &out, const Lens &lens); + +#include "lens.I" + +#endif + diff --git a/panda/src/gobj/orthoProjection.I b/panda/src/gobj/orthoProjection.I deleted file mode 100644 index 3a59bebce5..0000000000 --- a/panda/src/gobj/orthoProjection.I +++ /dev/null @@ -1,41 +0,0 @@ -// Filename: orthoProjection.I -// Created by: mike (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE OrthoProjection:: -OrthoProjection(const Frustumf &frustum) : _frustum(frustum) { -} - - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::get_frustum -// Access: Public -// Description: Returns the frustum that defines the perspective -// projection. -//////////////////////////////////////////////////////////////////// -INLINE const Frustumf &OrthoProjection:: -get_frustum() const { - return _frustum; -} - - - diff --git a/panda/src/gobj/orthoProjection.cxx b/panda/src/gobj/orthoProjection.cxx deleted file mode 100644 index 86b2a3211e..0000000000 --- a/panda/src/gobj/orthoProjection.cxx +++ /dev/null @@ -1,142 +0,0 @@ -// Filename: orthoProjection.cxx -// Created by: mike (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "geomLine.h" -#include "orthoProjection.h" - -#include - -TypeHandle OrthoProjection::_type_handle; - - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::make_copy -// Access: Public, Virtual -// Description: Allocates a new Projection just like this one. -//////////////////////////////////////////////////////////////////// -Projection *OrthoProjection:: -make_copy() const { - return new OrthoProjection(*this); -} - - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::get_projection_mat -// Access: Public, Virtual -// Description: This computes a transform matrix that performs the -// orthographic transform defined by the frustum. -//////////////////////////////////////////////////////////////////// -LMatrix4f OrthoProjection:: -get_projection_mat(CoordinateSystem cs) const { - return _frustum.get_ortho_projection_mat(cs); -} - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::make_geometry -// Access: Public, Virtual -// Description: Creates a GeomLine that describes the shape of the -// frustum for this projection -//////////////////////////////////////////////////////////////////// -Geom *OrthoProjection:: -make_geometry(const Colorf &color, - CoordinateSystem cs) const { - Vertexf rtn, ltn, lbn, rbn; - Vertexf rtf, ltf, lbf, rbf; - - // x, y, and z here refer to the right, forward, and up vectors, - // which are not necessarily the x, y, and z axes. - - LVector3f x = LVector3f::right(cs); - LVector3f y = LVector3f::forward(cs); - LVector3f z = LVector3f::up(cs); - LPoint3f o = LPoint3f::origin(cs); - - Vertexf xl = x * _frustum._l; - Vertexf xr = x * _frustum._r; - Vertexf zt = z * _frustum._t; - Vertexf zb = z * _frustum._b; - Vertexf yn = o + (y * _frustum._fnear); - - rtn = yn + zt + xr; - ltn = yn + zt + xl; - lbn = yn + zb + xl; - rbn = yn + zb + xr; - - float fs = _frustum._ffar / _frustum._fnear; - Vertexf yf = o + (y * _frustum._ffar); - - rtf = yf + ((zt + xr) * fs); - ltf = yf + ((zt + xl) * fs); - lbf = yf + ((zb + xl) * fs); - rbf = yf + ((zb + xr) * fs); - - PTA_Vertexf coords=PTA_Vertexf::empty_array(0); - PTA_ushort vindex=PTA_ushort::empty_array(0); - PTA_Colorf colors=PTA_Colorf::empty_array(0); - - // We just specify overall color - colors.push_back(color); - - coords.push_back(rtn); - coords.push_back(ltn); - coords.push_back(lbn); - coords.push_back(rbn); - coords.push_back(rtf); - coords.push_back(ltf); - coords.push_back(lbf); - coords.push_back(rbf); - coords.push_back(o); - - // Draw the near plane - vindex.push_back(0); vindex.push_back(1); - vindex.push_back(1); vindex.push_back(2); - vindex.push_back(2); vindex.push_back(3); - vindex.push_back(3); vindex.push_back(0); - - // Draw the far plane - vindex.push_back(4); vindex.push_back(5); - vindex.push_back(5); vindex.push_back(6); - vindex.push_back(6); vindex.push_back(7); - vindex.push_back(7); vindex.push_back(4); - - // Draw lines from eye to the corners - vindex.push_back(8); vindex.push_back(4); - vindex.push_back(8); vindex.push_back(5); - vindex.push_back(8); vindex.push_back(6); - vindex.push_back(8); vindex.push_back(7); - - GeomLine* gline = new GeomLine; - gline->set_coords(coords, vindex); - gline->set_colors(colors, G_OVERALL); - gline->set_num_prims(12); - - return gline; -} - -//////////////////////////////////////////////////////////////////// -// Function: OrthoProjection::make_bounds -// Access: Public, Virtual -// Description: Allocates and returns a new BoundingVolume that -// encloses the frustum used for this kind of -// projection, if possible. If a suitable bounding -// volume cannot be created, returns NULL. -//////////////////////////////////////////////////////////////////// -BoundingVolume *OrthoProjection:: -make_bounds(CoordinateSystem cs) const { - return new BoundingHexahedron(_frustum, true, cs); -} diff --git a/panda/src/sgraph/projectionNode.I b/panda/src/gobj/orthographicLens.I similarity index 62% rename from panda/src/sgraph/projectionNode.I rename to panda/src/gobj/orthographicLens.I index 66db1f0cfa..6a9a5cb849 100644 --- a/panda/src/sgraph/projectionNode.I +++ b/panda/src/gobj/orthographicLens.I @@ -1,5 +1,5 @@ -// Filename: projectionNode.I -// Created by: drose (23May00) +// Filename: orthographicLens.I +// Created by: mike (18Feb99) // //////////////////////////////////////////////////////////////////// // @@ -17,42 +17,30 @@ //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::Constructor +// Function: OrthographicLens::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE ProjectionNode:: -ProjectionNode(const string &name) : - NamedNode(name) -{ +INLINE OrthographicLens:: +OrthographicLens() { } //////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::Copy Constructor +// Function: OrthographicLens::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE ProjectionNode:: -ProjectionNode(const ProjectionNode ©) : - NamedNode(copy), - _projection(copy._projection) -{ +INLINE OrthographicLens:: +OrthographicLens(const OrthographicLens ©) : Lens(copy) { } //////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::Copy Assignment Operator +// Function: OrthographicLens::Copy Assignment Operator // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE void ProjectionNode:: -operator = (const ProjectionNode ©) { - NamedNode::operator = (copy); - _projection = copy._projection; +INLINE void OrthographicLens:: +operator = (const OrthographicLens ©) { + Lens::operator = (copy); } -INLINE ostream &operator << (ostream &out, const ProjectionNode &projnode) { - projnode.output(out); - return out; -} - - diff --git a/panda/src/gobj/orthographicLens.cxx b/panda/src/gobj/orthographicLens.cxx new file mode 100644 index 0000000000..ada28bce4c --- /dev/null +++ b/panda/src/gobj/orthographicLens.cxx @@ -0,0 +1,114 @@ +// Filename: orthographicLens.cxx +// Created by: mike (18Feb99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "orthographicLens.h" +#include "indent.h" + +TypeHandle OrthographicLens::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::make_copy +// Access: Public, Virtual +// Description: Allocates a new Lens just like this one. +//////////////////////////////////////////////////////////////////// +PT(Lens) OrthographicLens:: +make_copy() const { + return new OrthographicLens(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::is_linear +// Access: Published, Virtual +// Description: Returns true if the lens represents a linear +// projection (e.g. PerspectiveLens, OrthographicLens), +// and therefore there is a valid matrix returned by +// get_projection_mat(), or false otherwise. +//////////////////////////////////////////////////////////////////// +bool OrthographicLens:: +is_linear() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void OrthographicLens:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << get_type() << " film size = " << get_film_size() << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::compute_projection_mat +// Access: Protected, Virtual +// Description: Computes the complete transformation matrix from 3-d +// point to 2-d point, if the lens is linear. +//////////////////////////////////////////////////////////////////// +void OrthographicLens:: +compute_projection_mat() { + CoordinateSystem cs = _cs; + if (cs == CS_default) { + cs = default_coordinate_system; + } + + float a = 2.0f / (_far_distance - _near_distance); + float b = -(_far_distance + _near_distance) / (_far_distance - _near_distance); + + LMatrix4f canonical; + switch (cs) { + case CS_zup_right: + canonical.set(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, a, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, b, 1.0f); + break; + + case CS_yup_right: + canonical.set(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -a, 0.0f, + 0.0f, 0.0f, b, 1.0f); + break; + + case CS_zup_left: + canonical.set(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -a, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, b, 1.0f); + break; + + case CS_yup_left: + canonical.set(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, a, 0.0f, + 0.0f, 0.0f, b, 1.0f); + break; + + default: + gobj_cat.error() + << "Invalid coordinate system " << (int)cs << " in PerspectiveLens!\n"; + canonical = LMatrix4f::ident_mat(); + } + + + _projection_mat = get_lens_mat_inv() * canonical * get_film_mat(); + adjust_comp_flags(CF_projection_mat_inv, + CF_projection_mat); +} diff --git a/panda/src/gobj/orthographicLens.h b/panda/src/gobj/orthographicLens.h new file mode 100644 index 0000000000..2d3873ba5b --- /dev/null +++ b/panda/src/gobj/orthographicLens.h @@ -0,0 +1,75 @@ +// Filename: orthographicLens.h +// Created by: mike (18Feb99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef ORTHOGRAPHICLENS_H +#define ORTHOGRAPHICLENS_H + +#include "pandabase.h" + +#include "lens.h" + + +//////////////////////////////////////////////////////////////////// +// Class : OrthographicLens +// Description : An orthographic lens. Although this kind of lens is +// linear, like a PerspectiveLens, it doesn't respect +// field-of-view or focal length parameters, and +// adjusting these will have no effect. Instead, its +// field of view is controlled by adjusting the +// film_size; the orthographic lens represents a planar +// projection onto its imaginary film of the specified +// size, hanging in space. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA OrthographicLens : public Lens { +PUBLISHED: + INLINE OrthographicLens(); + +public: + INLINE OrthographicLens(const OrthographicLens ©); + INLINE void operator = (const OrthographicLens ©); + +public: + virtual PT(Lens) make_copy() const; + virtual bool is_linear() const; + + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + virtual void compute_projection_mat(); + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Lens::init_type(); + register_type(_type_handle, "OrthographicLens", + Lens::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "orthographicLens.I" + +#endif diff --git a/panda/src/gobj/perspectiveProjection.I b/panda/src/gobj/perspectiveLens.I similarity index 61% rename from panda/src/gobj/perspectiveProjection.I rename to panda/src/gobj/perspectiveLens.I index c145934fc9..8e13f32424 100644 --- a/panda/src/gobj/perspectiveProjection.I +++ b/panda/src/gobj/perspectiveLens.I @@ -1,4 +1,4 @@ -// Filename: perspectiveProjection.I +// Filename: perspectiveLens.I // Created by: drose (18Feb99) // //////////////////////////////////////////////////////////////////// @@ -17,28 +17,30 @@ //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::Constructor +// Function: PerspectiveLens::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE PerspectiveProjection:: -PerspectiveProjection(const Frustumf &frustum) : _frustum(frustum) { +INLINE PerspectiveLens:: +PerspectiveLens() { } - //////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::get_frustum +// Function: PerspectiveLens::Copy Constructor // Access: Public -// Description: Returns the frustum that defines the perspective -// projection. +// Description: //////////////////////////////////////////////////////////////////// -INLINE const Frustumf &PerspectiveProjection:: -get_frustum() const { - return _frustum; +INLINE PerspectiveLens:: +PerspectiveLens(const PerspectiveLens ©) : Lens(copy) { } -INLINE void PerspectiveProjection:: -set_frustum(const Frustumf &frust) { - _frustum = frust; +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PerspectiveLens:: +operator = (const PerspectiveLens ©) { + Lens::operator = (copy); } diff --git a/panda/src/gobj/perspectiveLens.cxx b/panda/src/gobj/perspectiveLens.cxx new file mode 100644 index 0000000000..580450ee8e --- /dev/null +++ b/panda/src/gobj/perspectiveLens.cxx @@ -0,0 +1,146 @@ +// Filename: perspectiveLens.cxx +// Created by: drose (18Feb99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "perspectiveLens.h" + +TypeHandle PerspectiveLens::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::make_copy +// Access: Public, Virtual +// Description: Allocates a new Lens just like this one. +//////////////////////////////////////////////////////////////////// +PT(Lens) PerspectiveLens:: +make_copy() const { + return new PerspectiveLens(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::is_linear +// Access: Published, Virtual +// Description: Returns true if the lens represents a linear +// projection (e.g. PerspectiveLens, OrthographicLens), +// and therefore there is a valid matrix returned by +// get_projection_mat(), or false otherwise. +//////////////////////////////////////////////////////////////////// +bool PerspectiveLens:: +is_linear() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::compute_projection_mat +// Access: Protected, Virtual +// Description: Computes the complete transformation matrix from 3-d +// point to 2-d point, if the lens is linear. +//////////////////////////////////////////////////////////////////// +void PerspectiveLens:: +compute_projection_mat() { + CoordinateSystem cs = _cs; + if (cs == CS_default) { + cs = default_coordinate_system; + } + + float fl = get_focal_length(); + float a = (_far_distance + _near_distance) / (_far_distance - _near_distance); + float b = -2.0f * _far_distance * _near_distance / (_far_distance - _near_distance); + + LMatrix4f canonical; + switch (cs) { + case CS_zup_right: + canonical.set( fl, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, a, 1.0f, + 0.0f, fl, 0.0f, 0.0f, + 0.0f, 0.0f, b, 0.0f); + break; + + case CS_yup_right: + canonical.set( fl, 0.0f, 0.0f, 0.0f, + 0.0f, fl, 0.0f, 0.0f, + 0.0f, 0.0f, -a, -1.0f, + 0.0f, 0.0f, b, 0.0f); + break; + + case CS_zup_left: + canonical.set( fl, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -a, -1.0f, + 0.0f, fl, 0.0f, 0.0f, + 0.0f, 0.0f, b, 0.0f); + break; + + case CS_yup_left: + canonical.set( fl, 0.0f, 0.0f, 0.0f, + 0.0f, fl, 0.0f, 0.0f, + 0.0f, 0.0f, a, 1.0f, + 0.0f, 0.0f, b, 0.0f); + break; + + default: + gobj_cat.error() + << "Invalid coordinate system " << (int)cs << " in PerspectiveLens!\n"; + canonical = LMatrix4f::ident_mat(); + } + + + _projection_mat = get_lens_mat_inv() * canonical * get_film_mat(); + adjust_comp_flags(CF_projection_mat_inv, + CF_projection_mat); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::fov_to_film +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a focal length, +// compute the correspdonding width (or height) on the +// film. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PerspectiveLens:: +fov_to_film(float fov, float focal_length, bool) const { + return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::fov_to_focal_length +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a width (or +// height) on the film, compute the focal length of the +// lens. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PerspectiveLens:: +fov_to_focal_length(float fov, float film_size, bool) const { + return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f)); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::film_to_fov +// Access: Protected, Virtual +// Description: Given a width (or height) on the film and a focal +// length, compute the field of view in degrees. If +// horiz is true, this is in the horizontal direction; +// otherwise, it is in the vertical direction (some +// lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PerspectiveLens:: +film_to_fov(float film_size, float focal_length, bool) const { + return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f; +} diff --git a/panda/src/gobj/orthoProjection.h b/panda/src/gobj/perspectiveLens.h similarity index 52% rename from panda/src/gobj/orthoProjection.h rename to panda/src/gobj/perspectiveLens.h index e6a756ec7d..d25e718019 100644 --- a/panda/src/gobj/orthoProjection.h +++ b/panda/src/gobj/perspectiveLens.h @@ -1,5 +1,5 @@ -// Filename: orthoProjection.h -// Created by: mike (18Feb99) +// Filename: perspectiveLens.h +// Created by: drose (18Feb99) // //////////////////////////////////////////////////////////////////// // @@ -16,37 +16,36 @@ // //////////////////////////////////////////////////////////////////// -#ifndef ORTHOPROJECTION_H -#define ORTHOPROJECTION_H +#ifndef PERSPECTIVELENS_H +#define PERSPECTIVELENS_H -#include +#include "pandabase.h" -#include "projection.h" -#include +#include "lens.h" //////////////////////////////////////////////////////////////////// -// Class : OrthoProjection -// Description : An orthographic-type projection, with a frustum. +// Class : PerspectiveLens +// Description : A perspective-type lens: a normal camera. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA OrthoProjection : public Projection { +class EXPCL_PANDA PerspectiveLens : public Lens { PUBLISHED: - INLINE OrthoProjection(const Frustumf &frustum); + INLINE PerspectiveLens(); public: - virtual Projection *make_copy() const; - virtual LMatrix4f get_projection_mat(CoordinateSystem cs = CS_default) const; - - virtual Geom* make_geometry(const Colorf &color = Colorf(0.0f, 1.0f, 0.0f, 1.0f), - CoordinateSystem cs = CS_default) const; - - virtual BoundingVolume *make_bounds(CoordinateSystem cs = CS_default) const; - - INLINE const Frustumf &get_frustum() const; + INLINE PerspectiveLens(const PerspectiveLens ©); + INLINE void operator = (const PerspectiveLens ©); +public: + virtual PT(Lens) make_copy() const; + virtual bool is_linear() const; protected: - Frustumf _frustum; + virtual void compute_projection_mat(); + + virtual float fov_to_film(float fov, float focal_length, bool horiz) const; + virtual float fov_to_focal_length(float fov, float film_size, bool horiz) const; + virtual float film_to_fov(float film_size, float focal_length, bool horiz) const; public: virtual TypeHandle get_type() const { @@ -57,17 +56,15 @@ public: return _type_handle; } static void init_type() { - Projection::init_type(); - register_type(_type_handle, "OrthoProjection", - Projection::get_class_type()); + Lens::init_type(); + register_type(_type_handle, "PerspectiveLens", + Lens::get_class_type()); } private: static TypeHandle _type_handle; }; -#include "orthoProjection.I" +#include "perspectiveLens.I" #endif - - diff --git a/panda/src/gobj/perspectiveProjection.cxx b/panda/src/gobj/perspectiveProjection.cxx deleted file mode 100644 index 8b8cc30b83..0000000000 --- a/panda/src/gobj/perspectiveProjection.cxx +++ /dev/null @@ -1,219 +0,0 @@ -// Filename: perspectiveProjection.cxx -// Created by: drose (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "geomLine.h" -#include "perspectiveProjection.h" - -#include - - -TypeHandle PerspectiveProjection::_type_handle; - - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::make_copy -// Access: Public, Virtual -// Description: Allocates a new Projection just like this one. -//////////////////////////////////////////////////////////////////// -Projection *PerspectiveProjection:: -make_copy() const { - return new PerspectiveProjection(*this); -} - - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::get_projection_mat -// Access: Public, Virtual -// Description: This computes a transform matrix that performs the -// perspective transform defined by the frustum. -//////////////////////////////////////////////////////////////////// -LMatrix4f PerspectiveProjection:: -get_projection_mat(CoordinateSystem cs) const { - return _frustum.get_perspective_projection_mat(cs); -} - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::make_geometry -// Access: Public, Virtual -// Description: Creates a GeomLine that describes the shape of the -// frustum for this projection -//////////////////////////////////////////////////////////////////// -Geom *PerspectiveProjection:: -make_geometry(const Colorf &color, - CoordinateSystem cs) const { - Vertexf rtn, ltn, lbn, rbn; - Vertexf rtf, ltf, lbf, rbf; - - // x, y, and z here refer to the right, forward, and up vectors, - // which are not necessarily the x, y, and z axes. - - LVector3f x = LVector3f::right(cs); - LVector3f y = LVector3f::forward(cs); - LVector3f z = LVector3f::up(cs); - LPoint3f o = LPoint3f::origin(cs); - - Vertexf xl = x * _frustum._l; - Vertexf xr = x * _frustum._r; - Vertexf zt = z * _frustum._t; - Vertexf zb = z * _frustum._b; - Vertexf yn = o + (y * _frustum._fnear); - - rtn = yn + zt + xr; - ltn = yn + zt + xl; - lbn = yn + zb + xl; - rbn = yn + zb + xr; - - float fs = _frustum._ffar / _frustum._fnear; - Vertexf yf = o + (y * _frustum._ffar); - - rtf = yf + ((zt + xr) * fs); - ltf = yf + ((zt + xl) * fs); - lbf = yf + ((zb + xl) * fs); - rbf = yf + ((zb + xr) * fs); - - PTA_Vertexf coords=PTA_Vertexf::empty_array(0); - PTA_ushort vindex=PTA_ushort::empty_array(0); - PTA_Colorf colors=PTA_Colorf::empty_array(0); - - // We just specify overall color - colors.push_back(color); - - coords.push_back(rtn); - coords.push_back(ltn); - coords.push_back(lbn); - coords.push_back(rbn); - coords.push_back(rtf); - coords.push_back(ltf); - coords.push_back(lbf); - coords.push_back(rbf); - coords.push_back(o); - - // Draw the near plane - vindex.push_back(0); vindex.push_back(1); - vindex.push_back(1); vindex.push_back(2); - vindex.push_back(2); vindex.push_back(3); - vindex.push_back(3); vindex.push_back(0); - - // Draw the far plane - vindex.push_back(4); vindex.push_back(5); - vindex.push_back(5); vindex.push_back(6); - vindex.push_back(6); vindex.push_back(7); - vindex.push_back(7); vindex.push_back(4); - - // Draw lines from eye to the corners - vindex.push_back(8); vindex.push_back(4); - vindex.push_back(8); vindex.push_back(5); - vindex.push_back(8); vindex.push_back(6); - vindex.push_back(8); vindex.push_back(7); - - GeomLine* gline = new GeomLine; - gline->set_coords(coords, vindex); - gline->set_colors(colors, G_OVERALL); - gline->set_num_prims(12); - - return gline; -} - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::make_bounds -// Access: Public, Virtual -// Description: Allocates and returns a new BoundingVolume that -// encloses the frustum used for this kind of -// projection, if possible. If a suitable bounding -// volume cannot be created, returns NULL. -//////////////////////////////////////////////////////////////////// -BoundingVolume *PerspectiveProjection:: -make_bounds(CoordinateSystem cs) const { - return new BoundingHexahedron(_frustum, false, cs); -} - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::extrude -// Access: Public, Virtual -// Description: Given a 2-d point in the range (-1,1) in both -// dimensions, where (0,0) is the center of the -// projection and (-1,-1) is the lower-left corner, -// compute the corresponding vector in space that maps -// to this point, if such a vector can be determined. -// Returns true if the vector is defined (in which case -// origin and direction are set to define the vector), -// or false otherwise. -//////////////////////////////////////////////////////////////////// -bool PerspectiveProjection:: -extrude(const LPoint2f &point2d, LPoint3f &origin, LVector3f &direction, - CoordinateSystem cs) const { - if (point2d[0] < -1 || point2d[0] > 1 || - point2d[1] < -1 || point2d[1] > 1) { - // The point is off the near plane. - return false; - } - - // Scale the point from (-1,1) to the range of the frustum. - - LPoint2f scaled(_frustum._l + 0.5f * (point2d[0] + 1.0f) * - (_frustum._r - _frustum._l), - _frustum._b + 0.5f * (point2d[1] + 1.0f) * - (_frustum._t - _frustum._b)); - - LVector3f near_vector = - LVector3f::rfu(scaled[0], _frustum._fnear, scaled[1], cs); - LVector3f far_vector = - near_vector * _frustum._ffar / _frustum._fnear; - - origin = LPoint3f::origin(cs) + near_vector; - direction = far_vector - near_vector; - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PerspectiveProjection::project -// Access: Public, Virtual -// Description: Given a 3-d point in space, determine the 2-d point -// this maps to, in the range (-1,1) in both dimensions, -// where (0,0) is the center of the projection and -// (-1,-1) is the lower-left corner. Returns true if -// the 3-d point is in front of the projection and -// within the viewing frustum (in which case point2d is -// filled in), or false otherwise. -//////////////////////////////////////////////////////////////////// -bool PerspectiveProjection:: -project(const LPoint3f &point3d, LPoint2f &point2d, - CoordinateSystem cs) const { - float f = point3d.dot(LVector3f::forward(cs)); - if (f < _frustum._fnear || f > _frustum._ffar) { - // The point is outside the near or far clipping planes. - return false; - } - - float r = point3d.dot(LVector3f::right(cs)); - float u = point3d.dot(LVector3f::up(cs)); - - LPoint2f scaled(r * _frustum._fnear / f, u * _frustum._fnear / f); - - if (scaled[0] < _frustum._l || scaled[0] > _frustum._r || - scaled[1] < _frustum._b || scaled[1] > _frustum._t) { - // The point is outside of the edge planes. - return false; - } - - point2d.set((scaled[0] - _frustum._l) * 2.0f / - (_frustum._r - _frustum._l) - 1.0f, - (scaled[1] - _frustum._b) * 2.0f / - (_frustum._t - _frustum._b) - 1.0f); - return true; -} diff --git a/panda/src/gobj/perspectiveProjection.h b/panda/src/gobj/perspectiveProjection.h deleted file mode 100644 index a402a41028..0000000000 --- a/panda/src/gobj/perspectiveProjection.h +++ /dev/null @@ -1,79 +0,0 @@ -// Filename: perspectiveProjection.h -// Created by: drose (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef PERSPECTIVEPROJECTION_H -#define PERSPECTIVEPROJECTION_H - -#include - -#include "projection.h" -#include - - -//////////////////////////////////////////////////////////////////// -// Class : PerspectiveProjection -// Description : A perspective-type projection, with a frustum. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA PerspectiveProjection : public Projection { -PUBLISHED: - INLINE PerspectiveProjection(const Frustumf &frustum); - -public: - virtual Projection *make_copy() const; - virtual LMatrix4f get_projection_mat(CoordinateSystem cs = CS_default) const; - - virtual Geom* make_geometry(const Colorf &color = Colorf(0.0f, 1.0f, 0.0f, 1.0f), - CoordinateSystem cs = CS_default) const; - - virtual BoundingVolume *make_bounds(CoordinateSystem cs = CS_default) const; - - virtual bool extrude(const LPoint2f &point2d, - LPoint3f &origin, LVector3f &direction, - CoordinateSystem cs = CS_default) const; - virtual bool project(const LPoint3f &point3d, LPoint2f &point2d, - CoordinateSystem cs) const; - - INLINE const Frustumf &get_frustum() const; - INLINE void set_frustum(const Frustumf &frust); - -protected: - Frustumf _frustum; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - Projection::init_type(); - register_type(_type_handle, "PerspectiveProjection", - Projection::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "perspectiveProjection.I" - -#endif - - diff --git a/panda/src/gobj/projection.cxx b/panda/src/gobj/projection.cxx deleted file mode 100644 index 91009eaa3a..0000000000 --- a/panda/src/gobj/projection.cxx +++ /dev/null @@ -1,81 +0,0 @@ -// Filename: projection.cxx -// Created by: drose (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#include "projection.h" - -TypeHandle Projection::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: Projection::make_geometry -// Access: Public, Virtual -// Description: Allocates and returns a new Geom that can be rendered -// to show a visible representation of the frustum used -// for this kind of projection, if it makes sense to do -// so. If a visible representation cannot be created, -// returns NULL. -//////////////////////////////////////////////////////////////////// -Geom *Projection:: -make_geometry(const Colorf &, CoordinateSystem) const { - return (Geom *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: Projection::make_bounds -// Access: Public, Virtual -// Description: Allocates and returns a new BoundingVolume that -// encloses the frustum used for this kind of -// projection, if possible. If a suitable bounding -// volume cannot be created, returns NULL. -//////////////////////////////////////////////////////////////////// -BoundingVolume *Projection:: -make_bounds(CoordinateSystem) const { - return (BoundingVolume *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: Projection::extrude -// Access: Public, Virtual -// Description: Given a 2-d point in the range (-1,1) in both -// dimensions, where (0,0) is the center of the -// projection and (-1,-1) is the lower-left corner, -// compute the corresponding vector in space that maps -// to this point, if such a vector can be determined. -// Returns true if the vector is defined (in which case -// origin and direction are set to define the vector), -// or false otherwise. -//////////////////////////////////////////////////////////////////// -bool Projection:: -extrude(const LPoint2f &, LPoint3f &, LVector3f &, CoordinateSystem) const { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: Projection::project -// Access: Public, Virtual -// Description: Given a 3-d point in space, determine the 2-d point -// this maps to, in the range (-1,1) in both dimensions, -// where (0,0) is the center of the projection and -// (-1,-1) is the lower-left corner. Returns true if -// the 3-d point is in front of the projection and -// within the viewing frustum (in which case point2d is -// filled in), or false otherwise. -//////////////////////////////////////////////////////////////////// -bool Projection:: -project(const LPoint3f &, LPoint2f &, CoordinateSystem) const { - return false; -} diff --git a/panda/src/gobj/projection.h b/panda/src/gobj/projection.h deleted file mode 100644 index bd08012ece..0000000000 --- a/panda/src/gobj/projection.h +++ /dev/null @@ -1,72 +0,0 @@ -// Filename: projection.h -// Created by: drose (18Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - -#ifndef PROJECTION_H -#define PROJECTION_H - -#include - -#include -#include -#include "geom.h" - -class BoundingVolume; - -//////////////////////////////////////////////////////////////////// -// Class : Projection -// Description : A base class for any number of different kinds of -// linear projections. Presently, this includes -// perspective and orthographic projections. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Projection : public TypedReferenceCount { -PUBLISHED: - virtual Projection *make_copy() const=0; - - virtual bool extrude(const LPoint2f &point2d, - LPoint3f &origin, LVector3f &direction, - CoordinateSystem cs = CS_default) const; - virtual bool project(const LPoint3f &point3d, LPoint2f &point2d, - CoordinateSystem cs = CS_default) const; - -public: - virtual LMatrix4f get_projection_mat(CoordinateSystem cs = CS_default) const=0; - virtual Geom* make_geometry(const Colorf &color = Colorf(0.0, 1.0, 0.0, 1.0), - CoordinateSystem cs = CS_default) const; - - virtual BoundingVolume *make_bounds(CoordinateSystem cs = CS_default) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "Projection", - TypedReferenceCount::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif - diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index d8c0ef008b..8444cfa8ca 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -83,8 +83,8 @@ class Spotlight; class AmbientLight; class DisplayRegion; -class Projection; -class ProjectionNode; +class Lens; +class LensNode; //////////////////////////////////////////////////////////////////// // Class : GraphicsStateGuardianBase diff --git a/panda/src/light/directionalLight.cxx b/panda/src/light/directionalLight.cxx index 11a09bb80e..0512ea4546 100644 --- a/panda/src/light/directionalLight.cxx +++ b/panda/src/light/directionalLight.cxx @@ -18,7 +18,6 @@ #include #include "directionalLight.h" -#include #include //////////////////////////////////////////////////////////////////// diff --git a/panda/src/light/spotlight.cxx b/panda/src/light/spotlight.cxx index 0eda05011c..594066e54c 100644 --- a/panda/src/light/spotlight.cxx +++ b/panda/src/light/spotlight.cxx @@ -20,7 +20,7 @@ #include "config_light.h" #include -#include +#include #include #include #include @@ -39,7 +39,7 @@ TypeHandle Spotlight::_type_handle; // Access: // Description: //////////////////////////////////////////////////////////////////// -Spotlight::Spotlight(const string& name) : ProjectionNode(name) +Spotlight::Spotlight(const string& name) : LensNode(name) { set_exponent(1); @@ -84,17 +84,16 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// float Spotlight::get_cutoff_angle(void) const { - Projection* proj = ((ProjectionNode *)this)->get_projection(); - Frustumf frustum; + Lens* proj = ((LensNode *)this)->get_lens(); float cutoff = 0; - if (proj->get_type() == PerspectiveProjection::get_class_type()) { - frustum = ((PerspectiveProjection *)proj)->get_frustum(); - cutoff = rad_2_deg(atan(frustum._t / frustum._fnear)); + if (proj->get_type() == PerspectiveLens::get_class_type()) { + const LVecBase2f &fov = ((PerspectiveLens *)proj)->get_fov(); + cutoff = fov[0]; } else light_cat.error() << "Spotlight::get_cutoff_angle() - spotlight has a non " - << "perspective projection!" << endl; + << "perspective lens!" << endl; return cutoff; } diff --git a/panda/src/light/spotlight.h b/panda/src/light/spotlight.h index d54a3f05d5..ba2962948a 100644 --- a/panda/src/light/spotlight.h +++ b/panda/src/light/spotlight.h @@ -29,7 +29,7 @@ #include #include #include "light.h" -#include +#include //////////////////////////////////////////////////////////////////// // Defines @@ -39,7 +39,7 @@ // Class : Spotlight // Description : //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Spotlight : public Light, public ProjectionNode +class EXPCL_PANDA Spotlight : public Light, public LensNode { PUBLISHED: @@ -91,10 +91,10 @@ class EXPCL_PANDA Spotlight : public Light, public ProjectionNode } static void init_type( void ) { Light::init_type(); - ProjectionNode::init_type(); + LensNode::init_type(); register_type( _type_handle, "Spotlight", Light::get_class_type(), - ProjectionNode::get_class_type() ); + LensNode::get_class_type() ); } virtual TypeHandle get_type( void ) const { return get_class_type(); diff --git a/panda/src/linmath/cmath.I b/panda/src/linmath/cmath.I index 7e3c70b209..8790b5e454 100644 --- a/panda/src/linmath/cmath.I +++ b/panda/src/linmath/cmath.I @@ -34,6 +34,10 @@ INLINE_LINMATH float ccos(float v) { return cosf(v); } +INLINE_LINMATH float ctan(float v) { + return tanf(v); +} + INLINE_LINMATH void sincosf(float v, float *pSinResult, float *pCosResult) { @@ -84,6 +88,10 @@ INLINE_LINMATH float cabs(float v) { return fabs(v); } +INLINE_LINMATH float catan(float v) { + return atanf(v); +} + INLINE_LINMATH float catan2(float y, float x) { return atan2f(y, x); } @@ -100,10 +108,18 @@ INLINE_LINMATH double ccos(double v) { return cos(v); } +INLINE_LINMATH double ctan(double v) { + return tan(v); +} + INLINE_LINMATH double cabs(double v) { return fabs(v); } +INLINE_LINMATH double catan(double v) { + return atan(v); +} + INLINE_LINMATH double catan2(double y, double x) { return atan2(y, x); } diff --git a/panda/src/linmath/cmath.h b/panda/src/linmath/cmath.h index c4fc832ce9..c9d088551a 100644 --- a/panda/src/linmath/cmath.h +++ b/panda/src/linmath/cmath.h @@ -32,14 +32,18 @@ INLINE_LINMATH float csqrt(float v); INLINE_LINMATH float csin(float v); INLINE_LINMATH float ccos(float v); +INLINE_LINMATH float ctan(float v); INLINE_LINMATH void csincos(float v, float *pSinResult, float *pCosResult); // does both at once (faster on x86) INLINE_LINMATH float cabs(float v); +INLINE_LINMATH float catan(float v); INLINE_LINMATH float catan2(float y, float x); INLINE_LINMATH double csqrt(double v); INLINE_LINMATH double csin(double v); INLINE_LINMATH double ccos(double v); +INLINE_LINMATH double ctan(double v); INLINE_LINMATH double cabs(double v); +INLINE_LINMATH double catan(double v); INLINE_LINMATH double catan2(double y, double x); INLINE_LINMATH void csincos(double v, double *pSinResult, double *pCosResult); // does both at once (faster on x86) diff --git a/panda/src/mathutil/boundingHexahedron.cxx b/panda/src/mathutil/boundingHexahedron.cxx index c12d8a3caf..253507670b 100644 --- a/panda/src/mathutil/boundingHexahedron.cxx +++ b/panda/src/mathutil/boundingHexahedron.cxx @@ -60,6 +60,25 @@ BoundingHexahedron(const Frustumf &frustum, bool is_ortho, } } +BoundingHexahedron:: +BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr, + const LPoint3f &fur, const LPoint3f &ful, + const LPoint3f &nll, const LPoint3f &nlr, + const LPoint3f &nur, const LPoint3f &nul) { + _points[0] = fll; + _points[1] = flr; + _points[2] = fur; + _points[3] = ful; + _points[4] = nll; + _points[5] = nlr; + _points[6] = nur; + _points[7] = nul; + + _flags = 0; + set_centroid(); + set_planes(); +} + BoundingVolume *BoundingHexahedron:: make_copy() const { return new BoundingHexahedron(*this); diff --git a/panda/src/mathutil/boundingHexahedron.h b/panda/src/mathutil/boundingHexahedron.h index 80050b3362..c0b4bb8c99 100644 --- a/panda/src/mathutil/boundingHexahedron.h +++ b/panda/src/mathutil/boundingHexahedron.h @@ -43,6 +43,10 @@ public: INLINE_MATHUTIL BoundingHexahedron(); BoundingHexahedron(const Frustumf &frustum, bool is_ortho, CoordinateSystem cs = CS_default); + BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr, + const LPoint3f &fur, const LPoint3f &ful, + const LPoint3f &nll, const LPoint3f &nlr, + const LPoint3f &nur, const LPoint3f &nul); virtual BoundingVolume *make_copy() const; virtual LPoint3f get_min() const; diff --git a/panda/src/sgattrib/billboardTransition.cxx b/panda/src/sgattrib/billboardTransition.cxx index b9cd61158d..a9bfdaf2c5 100644 --- a/panda/src/sgattrib/billboardTransition.cxx +++ b/panda/src/sgattrib/billboardTransition.cxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -77,8 +77,8 @@ sub_render(NodeRelation *arc, const AllTransitionsWrapper &, // DisplayRegion may have some override in effect, so we ask the // DisplayRegion instead of the GSG. const DisplayRegion *dr = gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); - nassertr(camera != (ProjectionNode *)NULL, true); + LensNode *camera = dr->get_cull_frustum(); + nassertr(camera != (LensNode *)NULL, true); // And the relative coordinate space. LMatrix4f rel_mat; diff --git a/panda/src/sgraph/Sources.pp b/panda/src/sgraph/Sources.pp index b74da37421..37d5aca8ca 100644 --- a/panda/src/sgraph/Sources.pp +++ b/panda/src/sgraph/Sources.pp @@ -12,20 +12,20 @@ camera.I camera.h config_sgraph.h geomNode.I geomNode.h \ geomTransformer.I geomTransformer.h modelNode.I modelNode.h \ modelRoot.I modelRoot.h planeNode.I planeNode.h \ - projectionNode.I projectionNode.h renderTraverser.I \ + lensNode.I lensNode.h renderTraverser.I \ renderTraverser.h switchNode.I switchNode.h #define INCLUDED_SOURCES \ camera.cxx config_sgraph.cxx geomNode.cxx geomTransformer.cxx \ - modelNode.cxx modelRoot.cxx planeNode.cxx projectionNode.cxx \ + modelNode.cxx modelRoot.cxx planeNode.cxx lensNode.cxx \ renderTraverser.cxx switchNode.cxx #define INSTALL_HEADERS \ camera.I camera.h config_sgraph.h \ geomNode.I geomNode.h geomTransformer.I \ geomTransformer.h modelNode.I modelNode.h modelRoot.I \ - modelRoot.h planeNode.I planeNode.h projectionNode.I \ - projectionNode.h renderTraverser.I renderTraverser.h \ + modelRoot.h planeNode.I planeNode.h lensNode.I \ + lensNode.h renderTraverser.I renderTraverser.h \ switchNode.I switchNode.h #define IGATESCAN all diff --git a/panda/src/sgraph/camera.cxx b/panda/src/sgraph/camera.cxx index 10149878b5..e03ed8d095 100644 --- a/panda/src/sgraph/camera.cxx +++ b/panda/src/sgraph/camera.cxx @@ -15,17 +15,12 @@ // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// -#include +#include "pandabase.h" #include "camera.h" -#include -#include +#include "lens.h" +#include "throw_event.h" - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// TypeHandle Camera::_type_handle; -const std::string Camera::_CHANGE_CAM = "CamChange"; //////////////////////////////////////////////////////////////////// @@ -35,7 +30,7 @@ const std::string Camera::_CHANGE_CAM = "CamChange"; //////////////////////////////////////////////////////////////////// Camera:: Camera(const string &name) : - ProjectionNode(name), + LensNode(name), _active(true) { } @@ -47,7 +42,7 @@ Camera(const string &name) : //////////////////////////////////////////////////////////////////// Camera:: Camera(const Camera ©) : - ProjectionNode(copy), + LensNode(copy), _active(copy._active), _scene(copy._scene) { @@ -60,7 +55,7 @@ Camera(const Camera ©) : //////////////////////////////////////////////////////////////////// void Camera:: operator = (const Camera ©) { - ProjectionNode::operator = (copy); + LensNode::operator = (copy); _active = copy._active; _scene = copy._scene; } @@ -171,96 +166,3 @@ remove_display_region(DisplayRegion *display_region) { _display_regions.erase(dri); } } - -//////////////////////////////////////////////////////////////////// -// Function: Camera::set_* -// Access: Public -// Description: Overrides projection matrix functions. The intention -// is to throw a camera update event for recalculation -// of various parameters used by Direct, rather than -// recalculating everything every frame "just in case". -// When fully implemented, there will be more specific -// information for each event, e.g. -// throw_event(_CHANGE_FOV, get_name(), hfov, vfov) -//////////////////////////////////////////////////////////////////// -void Camera:: -set_projection(const Projection &projection) { - ProjectionNode::set_projection(projection); - if(has_name()) { - throw_event(_CHANGE_CAM,get_name()); - } - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_fov(float hfov) { - ProjectionNode::set_fov(hfov); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_fov(float hfov, float vfov) { - ProjectionNode::set_fov(hfov, vfov); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_hfov(float hfov) { - ProjectionNode::set_hfov(hfov); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_vfov(float vfov) { - ProjectionNode::set_vfov(vfov); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_aspect(float aspect) { - ProjectionNode::set_aspect(aspect); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_near_far(float cnear, float cfar) { - ProjectionNode::set_near_far(cnear,cfar); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_near(float cnear) { - ProjectionNode::set_near(cnear); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} - -void Camera:: -set_far(float cfar) { - ProjectionNode::set_far(cfar); - if(has_name()) - throw_event(_CHANGE_CAM,get_name()); - else - throw_event(_CHANGE_CAM,std::string("")); -} diff --git a/panda/src/sgraph/camera.h b/panda/src/sgraph/camera.h index 340726b105..5d75980517 100644 --- a/panda/src/sgraph/camera.h +++ b/panda/src/sgraph/camera.h @@ -21,24 +21,19 @@ //////////////////////////////////////////////////////////////////// // Includes //////////////////////////////////////////////////////////////////// -#include - -#include "projectionNode.h" - -#include +#include "pandabase.h" +#include "lensNode.h" +#include "pt_Node.h" #include "pvector.h" -//////////////////////////////////////////////////////////////////// -// Defines -//////////////////////////////////////////////////////////////////// class DisplayRegion; //////////////////////////////////////////////////////////////////// // Class : Camera // Description : //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Camera : public ProjectionNode { +class EXPCL_PANDA Camera : public LensNode { PUBLISHED: Camera(const string &name = ""); @@ -64,17 +59,6 @@ PUBLISHED: int get_num_drs() const; DisplayRegion *get_dr(int index) const; - void set_projection(const Projection &projection); - - void set_fov(float hfov); - void set_fov(float hfov, float vfov); - void set_hfov(float hfov); - void set_vfov(float vfov); - void set_aspect(float aspect); - void set_near_far(float cnear, float cfar); - void set_near(float cnear); - void set_far(float cfar); - private: void add_display_region(DisplayRegion *display_region); void remove_display_region(DisplayRegion *display_region); @@ -92,9 +76,9 @@ public: return _type_handle; } static void init_type() { - ProjectionNode::init_type(); + LensNode::init_type(); register_type(_type_handle, "Camera", - ProjectionNode::get_class_type()); + LensNode::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/sgraph/config_sgraph.cxx b/panda/src/sgraph/config_sgraph.cxx index 76e9b5ef09..b7c2f26a05 100644 --- a/panda/src/sgraph/config_sgraph.cxx +++ b/panda/src/sgraph/config_sgraph.cxx @@ -23,7 +23,7 @@ #include "planeNode.h" #include "modelNode.h" #include "modelRoot.h" -#include "projectionNode.h" +#include "lensNode.h" #include "switchNode.h" #include @@ -60,7 +60,7 @@ init_libsgraph() { PlaneNode::init_type(); ModelNode::init_type(); ModelRoot::init_type(); - ProjectionNode::init_type(); + LensNode::init_type(); SwitchNode::init_type(); //Registration of writeable object's creation diff --git a/panda/src/sgraph/geomTransformer.cxx b/panda/src/sgraph/geomTransformer.cxx index d6d4b020a7..7e51861f6e 100644 --- a/panda/src/sgraph/geomTransformer.cxx +++ b/panda/src/sgraph/geomTransformer.cxx @@ -56,7 +56,7 @@ transform_vertices(Geom *geom, const LMatrix4f &mat) { geom->get_coords(coords, index); - if (coords != NULL) { + if (!coords.empty()) { // Look up the Geom's coords in our table--have we already // transformed this array? SourceVertices sv; diff --git a/panda/src/sgraph/lensNode.I b/panda/src/sgraph/lensNode.I new file mode 100644 index 0000000000..a59ff410c0 --- /dev/null +++ b/panda/src/sgraph/lensNode.I @@ -0,0 +1,88 @@ +// Filename: lensNode.I +// Created by: drose (23May00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LensNode:: +LensNode(const string &name) : + NamedNode(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LensNode:: +LensNode(const LensNode ©) : + NamedNode(copy), + _lens(copy._lens) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void LensNode:: +operator = (const LensNode ©) { + NamedNode::operator = (copy); + _lens = copy._lens; +} + +//////////////////////////////////////////////////////////////////// +// Function: copy_lens +// Access: Public +// Description: Sets up the LensNode using a copy of the +// indicated Lens. If the original Lens is +// changed or destroyed, this LensNode is not +// affected. +//////////////////////////////////////////////////////////////////// +INLINE void LensNode:: +copy_lens(const Lens &lens) { + _lens = lens.make_copy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: set_lens +// Access: Public +// Description: Sets up the LensNode using this particular Lens +// pointer. If the lens is subsequently modified, the +// LensNode properties immediately reflect the change. +//////////////////////////////////////////////////////////////////// +INLINE void LensNode:: +set_lens(Lens *lens) { + _lens = lens; +} + +//////////////////////////////////////////////////////////////////// +// Function: get_lens +// Access: Public +// Description: Returns a pointer to the particular Lens +// associated with this LensNode, or NULL if there is +// not yet a Lens associated. +//////////////////////////////////////////////////////////////////// +INLINE Lens *LensNode:: +get_lens() { + return _lens; +} diff --git a/panda/src/sgraph/lensNode.cxx b/panda/src/sgraph/lensNode.cxx new file mode 100644 index 0000000000..03f1dab5cc --- /dev/null +++ b/panda/src/sgraph/lensNode.cxx @@ -0,0 +1,85 @@ +// Filename: lensNode.cxx +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// +#include "lensNode.h" +#include "geometricBoundingVolume.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Static variables +//////////////////////////////////////////////////////////////////// +TypeHandle LensNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +Node *LensNode:: +make_copy() const { + return new LensNode(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::is_in_view +// Access: Public +// Description: Returns true if the given point is within the bounds +// of the lens of the LensNode (i.e. if the camera can +// see the point). +//////////////////////////////////////////////////////////////////// +bool LensNode:: +is_in_view(const LPoint3f &pos) { + PT(BoundingVolume) bv = _lens->make_bounds(); + if (bv == NULL) + return false; + GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bv); + int ret = gbv->contains(pos); + return (ret != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LensNode:: +output(ostream &out) const { + NamedNode::output(out); + if (_lens != (Lens *)NULL) { + out << " ("; + _lens->output(out); + out << ")"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void LensNode:: +write(ostream &out, int indent_level) const { + NamedNode::write(out, indent_level); + if (_lens != (Lens *)NULL) { + _lens->write(out, indent_level + 2); + } +} + diff --git a/panda/src/sgraph/lensNode.h b/panda/src/sgraph/lensNode.h new file mode 100644 index 0000000000..37f442d255 --- /dev/null +++ b/panda/src/sgraph/lensNode.h @@ -0,0 +1,80 @@ +// Filename: lensNode.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// +#ifndef LENSNODE_H +#define LENSNODE_H +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include "pandabase.h" + +#include "namedNode.h" +#include "lens.h" + +//////////////////////////////////////////////////////////////////// +// Class : LensNode +// Description : A node that contains a Lens. The most important +// example of this kind of node is a Camera, but other +// kinds of nodes also contain a lens (for instance, a +// Spotlight). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA LensNode : public NamedNode { +PUBLISHED: + INLINE LensNode(const string &name = ""); + +public: + INLINE LensNode(const LensNode ©); + INLINE void operator = (const LensNode ©); + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + + virtual Node *make_copy() const; + +PUBLISHED: + INLINE void copy_lens(const Lens &lens); + INLINE void set_lens(Lens *lens); + INLINE Lens *get_lens(); + + bool is_in_view(const LPoint3f &pos); + +protected: + PT(Lens) _lens; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + NamedNode::init_type(); + register_type( _type_handle, "LensNode", + NamedNode::get_class_type() ); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + + static TypeHandle _type_handle; +}; + +#include "lensNode.I" + +#endif diff --git a/panda/src/sgraph/projectionNode.cxx b/panda/src/sgraph/projectionNode.cxx deleted file mode 100644 index e53c23b47c..0000000000 --- a/panda/src/sgraph/projectionNode.cxx +++ /dev/null @@ -1,367 +0,0 @@ -// Filename: projectionNode.cxx -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// -#include "projectionNode.h" -#include -#include -#include - -#include - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// -TypeHandle ProjectionNode::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::make_copy -// Access: Public, Virtual -// Description: Returns a newly-allocated Node that is a shallow copy -// of this one. It will be a different Node pointer, -// but its internal data may or may not be shared with -// that of the original Node. -//////////////////////////////////////////////////////////////////// -Node *ProjectionNode:: -make_copy() const { - return new ProjectionNode(*this); -} - -//////////////////////////////////////////////////////////////////// -// Function: set_projection -// Access: Public -// Description: Sets up the ProjectionNode using a copy of the -// indicated Projection. If the original Projection is -// changed or destroyed, this ProjectionNode is not -// affected. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_projection(const Projection &projection) { - _projection = projection.make_copy(); -} - -//////////////////////////////////////////////////////////////////// -// Function: share_projection -// Access: Public -// Description: This is similar to set_projection(), but the -// Projection is assigned by pointer. If the original -// Projection is changed, this ProjectionNode is -// immediately affected. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -share_projection(Projection *projection) { - _projection = projection; -} - -//////////////////////////////////////////////////////////////////// -// Function: get_projection -// Access: Public -// Description: Returns a pointer to the particular Projection -// associated with this ProjectionNode. -//////////////////////////////////////////////////////////////////// -Projection *ProjectionNode:: -get_projection() { - if (_projection == (Projection *)NULL) { - // If we have no projection yet, give us a default Projection. - Frustumf f; - _projection = new PerspectiveProjection(f); - } - - return _projection; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::is_in_view -// Access: Public -// Description: Returns true if the given point is within the bounds -// of the projection of the ProjectionNode (i.e. if the -// camera can see the point). -//////////////////////////////////////////////////////////////////// -bool ProjectionNode:: -is_in_view(const LPoint3f &pos) { - BoundingVolume *bv = _projection->make_bounds(); - if (bv == NULL) - return false; - GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bv); - int ret = gbv->contains(pos); - delete bv; - return (ret != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_perspective_params -// Access: Public -// Description: Gets the viewing parameters of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -get_perspective_params(float &yfov, float &aspect, float &cnear, - float &cfar) const { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - proj->get_frustum().get_perspective_params(yfov, aspect, cnear, cfar); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_perspective_params -// Access: Public -// Description: Gets the viewing parameters of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -get_perspective_params(float &xfov, float &yfov, float &aspect, float &cnear, - float &cfar) const { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - proj->get_frustum().get_perspective_params(xfov, yfov, aspect, cnear, - cfar); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_hfov -// Access: Public -// Description: Gets the horizontal field of view of the -// ProjectionNode, assuming it represents a perspective -// frustum. -//////////////////////////////////////////////////////////////////// -float ProjectionNode:: -get_hfov(void) const { - float xfov=0.0f, yfov=0.0f, aspect, cnear, cfar; - get_perspective_params(xfov, yfov, aspect, cnear, cfar); - return xfov; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_vfov -// Access: Public -// Description: Gets the vertical field of view of the -// ProjectionNode, assuming it represents a perspective -// frustum. -//////////////////////////////////////////////////////////////////// -float ProjectionNode:: -get_vfov(void) const { - float xfov=0.0f, yfov=0.0f, aspect, cnear, cfar; - get_perspective_params(xfov, yfov, aspect, cnear, cfar); - return yfov; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_aspect -// Access: Public -// Description: Gets the aspect ratio of the horizontal field of view -// to the vertical field of view, assuming we have a -// perspective frustum. -//////////////////////////////////////////////////////////////////// -float ProjectionNode:: -get_aspect(void) const { - float yfov, aspect=0.0f, cnear, cfar; - get_perspective_params(yfov, aspect, cnear, cfar); - return aspect; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_near_far -// Access: Public -// Description: Gets the near and far clipping planes, assuming we -// have a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -get_near_far(float &cnear, float &cfar) const { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - Frustumf frust = proj->get_frustum(); - cnear = frust._fnear; - cfar = frust._ffar; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_near -// Access: Public -// Description: Gets the near clipping plane, assuming we have a -// perspective frustum. -//////////////////////////////////////////////////////////////////// -float ProjectionNode:: -get_near(void) const { - float cnear, cfar; - get_near_far(cnear, cfar); - return cnear; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::get_far -// Access: Public -// Description: Gets the far clipping plane, assuming we have a -// perspective frustum. -//////////////////////////////////////////////////////////////////// -float ProjectionNode:: -get_far(void) const { - float cnear, cfar; - get_near_far(cnear, cfar); - return cfar; -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_fov -// Access: Public -// Description: Sets the field-of-view of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_fov(float hfov) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float tfov, ufov, aspect, cnear, cfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(tfov, ufov, aspect, cnear, cfar); - frust.make_perspective_hfov(hfov, aspect, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_fov -// Access: Public -// Description: Sets the field-of-view of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_fov(float hfov, float vfov) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float tfov, ufov, aspect, cnear, cfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(tfov, ufov, aspect, cnear, cfar); - frust.make_perspective(hfov, vfov, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_hfov -// Access: Public -// Description: Sets the horizontal field-of-view of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_hfov(float hfov) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float tfov, ufov, aspect, cnear, cfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(tfov, ufov, aspect, cnear, cfar); - frust.make_perspective(hfov, ufov, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_vfov -// Access: Public -// Description: Sets the vertical field-of-view of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_vfov(float vfov) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float tfov, ufov, aspect, cnear, cfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(tfov, ufov, aspect, cnear, cfar); - frust.make_perspective(tfov, vfov, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_aspect -// Access: Public -// Description: Sets the aspect ratio of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_aspect(float aspect) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float xfov, yfov, taspect, cnear, cfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(xfov, yfov, taspect, cnear, cfar); - // I don't know what to do when the aspect changes. I have arbitrarilly - // decided to preserved the horizontal FoV. The vertical will be - // recomputed based on the new aspect and the horizontal. - frust.make_perspective_hfov(xfov, aspect, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_near_far -// Access: Public -// Description: Sets the near and far planes of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_near_far(float cnear, float cfar) { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float xfov, yfov, aspect, tnear, tfar; - Frustumf frust = proj->get_frustum(); - frust.get_perspective_params(xfov, yfov, aspect, tnear, tfar); - frust.make_perspective(xfov, yfov, cnear, cfar); - proj->set_frustum(frust); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_near -// Access: Public -// Description: Sets the near clipping plane of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_near(float cnear) { - float cfar = get_far(); - set_near_far(cnear, cfar); -} - -//////////////////////////////////////////////////////////////////// -// Function: ProjectionNode::set_far -// Access: Public -// Description: Sets the far clipping plane of the ProjectionNode, -// assuming it represents a perspective frustum. -//////////////////////////////////////////////////////////////////// -void ProjectionNode:: -set_far(float cfar) { - float cnear = get_near(); - set_near_far(cnear, cfar); -} - -void ProjectionNode:: -output(ostream &out) const { - if (_projection->get_type() == PerspectiveProjection::get_class_type()) { - PerspectiveProjection *proj = DCAST(PerspectiveProjection, _projection); - float xfov,yfov,aspect_ratio,cnear,cfar; - proj->get_frustum().get_perspective_params(xfov, yfov, aspect_ratio, cnear, cfar); - - out << "X-FOV: " << xfov << " deg, Y-FOV: " << yfov << " deg" - << "Aspect ratio: " << aspect_ratio << ", Near plane: " << cnear << ", Far plane: " << cfar << endl; - } - - out << "Projection Matrix: " << _projection->get_projection_mat(CS_default) << endl; -} - diff --git a/panda/src/sgraph/projectionNode.h b/panda/src/sgraph/projectionNode.h deleted file mode 100644 index e4015e5d4a..0000000000 --- a/panda/src/sgraph/projectionNode.h +++ /dev/null @@ -1,97 +0,0 @@ -// Filename: projectionNode.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// -#ifndef PROJECTIONNODE_H -#define PROJECTIONNODE_H -// -//////////////////////////////////////////////////////////////////// -// Includes -//////////////////////////////////////////////////////////////////// -#include - -#include -#include - -//////////////////////////////////////////////////////////////////// -// Defines -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Class : ProjectionNode -// Description : A node that has a frustum -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA ProjectionNode : public NamedNode { -PUBLISHED: - INLINE ProjectionNode(const string &name = ""); - -public: - INLINE ProjectionNode(const ProjectionNode ©); - INLINE void operator = (const ProjectionNode ©); - void output(ostream &out) const; - virtual Node *make_copy() const; - -PUBLISHED: - void set_projection(const Projection &projection); - void share_projection(Projection *projection); - Projection *get_projection(); - - bool is_in_view(const LPoint3f &pos); - - void get_perspective_params(float &yfov, float &aspect, float &cnear, - float &cfar) const; - void get_perspective_params(float &xfov, float &yfov, float &aspect, - float &cnear, float &cfar) const; - float get_hfov(void) const; - float get_vfov(void) const; - void set_fov(float hfov); - void set_fov(float hfov, float vfov); - void set_hfov(float hfov); - void set_vfov(float vfov); - float get_aspect(void) const; - void set_aspect(float aspect); - void get_near_far(float &cnear, float &cfar) const; - void set_near_far(float cnear, float cfar); - float get_near(void) const; - void set_near(float cnear); - float get_far(void) const; - void set_far(float cfar); - -protected: - PT(Projection) _projection; - -public: - static TypeHandle get_class_type( void ) { - return _type_handle; - } - static void init_type( void ) { - NamedNode::init_type(); - register_type( _type_handle, "ProjectionNode", - NamedNode::get_class_type() ); - } - virtual TypeHandle get_type( void ) const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - - static TypeHandle _type_handle; -}; - -#include "projectionNode.I" - -#endif diff --git a/panda/src/sgraph/sgraph_composite2.cxx b/panda/src/sgraph/sgraph_composite2.cxx index ca13bb40c0..039e7730fc 100644 --- a/panda/src/sgraph/sgraph_composite2.cxx +++ b/panda/src/sgraph/sgraph_composite2.cxx @@ -1,7 +1,7 @@ #include "config_sgraph.cxx" #include "camera.cxx" -#include "projectionNode.cxx" +#include "lensNode.cxx" #include "renderTraverser.cxx" #include "switchNode.cxx" diff --git a/panda/src/sgraphutil/directRenderTraverser.cxx b/panda/src/sgraphutil/directRenderTraverser.cxx index c8b25cc332..664c8f955c 100644 --- a/panda/src/sgraphutil/directRenderTraverser.cxx +++ b/panda/src/sgraphutil/directRenderTraverser.cxx @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -101,7 +101,7 @@ traverse(Node *root, LMatrix4f rel_from_camera; NodeTransitionWrapper ntw(TransformTransition::get_class_type()); const DisplayRegion *dr = _gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); + LensNode *camera = dr->get_cull_frustum(); wrt(camera, root, begin(), end(), ntw, get_graph_type()); const TransformTransition *tt; if (get_transition_into(tt, ntw)) { diff --git a/panda/src/sgraphutil/frustumCullTraverser.I b/panda/src/sgraphutil/frustumCullTraverser.I index 2763554c33..ff41e38f23 100644 --- a/panda/src/sgraphutil/frustumCullTraverser.I +++ b/panda/src/sgraphutil/frustumCullTraverser.I @@ -48,29 +48,30 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root, // DisplayRegion may have some override in effect, so we ask the // DisplayRegion instead of the GSG. const DisplayRegion *dr = _gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); - if (camera != (const ProjectionNode *)NULL) { - const Projection *proj = camera->get_projection(); - nassertv(proj != (const Projection *)NULL); - BoundingVolume *bv = proj->make_bounds(); + LensNode *camera = dr->get_cull_frustum(); + if (camera != (const LensNode *)NULL) { + const Lens *lens = camera->get_lens(); + nassertv(lens != (const Lens *)NULL); + PT(BoundingVolume) bv = lens->make_bounds(); - if (bv->is_of_type(GeometricBoundingVolume::get_class_type())) { + if (bv != (BoundingVolume *)NULL && + bv->is_of_type(GeometricBoundingVolume::get_class_type())) { _view_frustum = DCAST(GeometricBoundingVolume, bv); - } else { - delete bv; } } - local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy()); - local_frustum->xform(rel_from_camera); - GraphicsStateGuardian::_frustum_cull_volumes_pcollector.add_level(1); - GraphicsStateGuardian::_frustum_cull_transforms_pcollector.add_level(1); - - if (sgraphutil_cat.is_spam()) { - sgraphutil_cat.spam() - << "Beginning frustum cull, frustum is: " << *local_frustum << "\n" - << "Transform is:\n"; - rel_from_camera.write(sgraphutil_cat.spam(false), 2); + if (_view_frustum != (GeometricBoundingVolume *)NULL) { + local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy()); + local_frustum->xform(rel_from_camera); + GraphicsStateGuardian::_frustum_cull_volumes_pcollector.add_level(1); + GraphicsStateGuardian::_frustum_cull_transforms_pcollector.add_level(1); + + if (sgraphutil_cat.is_spam()) { + sgraphutil_cat.spam() + << "Beginning frustum cull, frustum is: " << *local_frustum << "\n" + << "Transform is:\n"; + rel_from_camera.write(sgraphutil_cat.spam(false), 2); + } } } @@ -202,7 +203,7 @@ traverse(NodeRelation *arc, TransitionWrapper render_state, NodeTransitionWrapper ntw(TransformTransition::get_class_type()); const DisplayRegion *dr = _gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); + LensNode *camera = dr->get_cull_frustum(); wrt(camera, arc->get_child(), _arc_chain.begin(), _arc_chain.end(), ntw, _graph_type); diff --git a/panda/src/shader/shader.I b/panda/src/shader/shader.I index ab0723f8c8..c1e9c5b165 100644 --- a/panda/src/shader/shader.I +++ b/panda/src/shader/shader.I @@ -36,7 +36,7 @@ set_viz(Shader::Visualize* v) { // Description: //////////////////////////////////////////////////////////////////// INLINE int FrustumShader:: -add_frustum(ProjectionNode* frust) { +add_frustum(LensNode* frust) { make_dirty(); _frusta.push_back(frust); return (_frusta.size()); @@ -48,9 +48,9 @@ add_frustum(ProjectionNode* frust) { // Description: //////////////////////////////////////////////////////////////////// INLINE int FrustumShader:: -remove_frustum(ProjectionNode* frust) { +remove_frustum(LensNode* frust) { make_dirty(); - ProjectionVector::iterator i; + LensVector::iterator i; for (i = _frusta.begin(); i != _frusta.end(); ++i) { if ((*i) == frust) { _frusta.erase(i); diff --git a/panda/src/shader/shader.h b/panda/src/shader/shader.h index dc88d96bbb..469f3aa810 100644 --- a/panda/src/shader/shader.h +++ b/panda/src/shader/shader.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -120,14 +120,14 @@ public: virtual ~FrustumShader(void) { } INLINE int get_num_frusta(void) const { return _frusta.size(); } - INLINE int add_frustum(ProjectionNode* frust); - INLINE int remove_frustum(ProjectionNode* frust); + INLINE int add_frustum(LensNode* frust); + INLINE int remove_frustum(LensNode* frust); - typedef pvector ProjectionVector; + typedef pvector LensVector; protected: - ProjectionVector _frusta; + LensVector _frusta; public: diff --git a/panda/src/shader/spheretexHighlighter.cxx b/panda/src/shader/spheretexHighlighter.cxx index f4636014a7..c70b92d653 100644 --- a/panda/src/shader/spheretexHighlighter.cxx +++ b/panda/src/shader/spheretexHighlighter.cxx @@ -122,7 +122,7 @@ pre_apply(Node *node, const AllAttributesWrapper &init_state, // Figure out where the highlight is relative to the object's center and // the light - const ProjectionNode* projnode = gsg->get_current_projection_node(); + const LensNode* projnode = gsg->get_current_camera(); LVector3f model_pos = get_rel_pos(node, projnode); LVector3f norm_model_pos = normalize(model_pos); LPoint3f light_pos = get_rel_pos(light, projnode); diff --git a/panda/src/shader/spheretexReflector.cxx b/panda/src/shader/spheretexReflector.cxx index c41ef366d9..fdbc7ee5bf 100644 --- a/panda/src/shader/spheretexReflector.cxx +++ b/panda/src/shader/spheretexReflector.cxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -116,7 +116,7 @@ pre_apply(Node *node, const AllAttributesWrapper &init_state, state.clear_attribute(TransformTransition::get_class_type()); // Get the current camera from the gsg - const ProjectionNode* camera = gsg->get_current_projection_node(); + const LensNode* camera = gsg->get_current_camera(); // Save the clear color. Colorf clear_color = gsg->get_color_clear_value(); @@ -158,15 +158,16 @@ pre_apply(Node *node, const AllAttributesWrapper &init_state, arc->set_transition(new TransformTransition(mat)); } - // Build a ProjectionNode that represents a wide-angle view from the + // Build a LensNode that represents a wide-angle view from the // reflecting object towards the camera. - Frustumf frust; - frust.make_perspective_hfov(150.0f, 1.0f, _fnear, _ffar); - PerspectiveProjection projection(frust); - ProjectionNode* projnode = new ProjectionNode; - projnode->set_projection(projection); + PT(Lens) *lens = new PerspectiveLens; + lens->set_fov(150.0f); + lens->set_near(_fnear); + lens->set_far(_ffar); + LensNode *projnode = new LensNode; + projnode->set_lens(lens); - // How shall we rotate the ProjectionNode? + // How shall we rotate the LensNode? LMatrix4f r_mat; // Get camera pos in the coordinate space of the reflecting object diff --git a/panda/src/switchnode/LODNode.cxx b/panda/src/switchnode/LODNode.cxx index a3ec840f0a..dac85d9885 100644 --- a/panda/src/switchnode/LODNode.cxx +++ b/panda/src/switchnode/LODNode.cxx @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////// #include "LODNode.h" -#include "projectionNode.h" +#include "lensNode.h" #include "config_switchnode.h" #include "graphicsStateGuardian.h" @@ -92,8 +92,8 @@ compute_switch(RenderTraverser *trav) { // DisplayRegion may have some override in effect, so we ask the // DisplayRegion instead of the GSG. const DisplayRegion *dr = gsg->get_current_display_region(); - ProjectionNode *camera = dr->get_cull_frustum(); - if (camera != (ProjectionNode *)NULL) { + LensNode *camera = dr->get_cull_frustum(); + if (camera != (LensNode *)NULL) { LPoint3f camera_pos(0, 0, 0); // Get the LOD center in camera space diff --git a/panda/src/testbed/demo.cxx b/panda/src/testbed/demo.cxx index d15ad318ea..f891d83f0b 100644 --- a/panda/src/testbed/demo.cxx +++ b/panda/src/testbed/demo.cxx @@ -44,8 +44,6 @@ #include "renderRelation.h" #include "camera.h" #include "frustum.h" -#include "orthoProjection.h" -#include "perspectiveProjection.h" #include "textNode.h" #include "colorMatrixTransition.h" #include "alphaTransformTransition.h" @@ -102,121 +100,6 @@ RenderRelation *sky_arc = (RenderRelation *)NULL; RenderRelation *flare_arc = (RenderRelation *)NULL; -/* -void -setup_panda2d() { - static bool already_setup = false; - if (already_setup) { - nout << "Already have 2-d layer set up.\n"; - return; - } - already_setup = true; - nout << "Setting up 2-d layer.\n"; - - render2d_top = new NamedNode("render2d_top"); - render2d = new NamedNode("render2d"); - render2d_arc = new RenderRelation(render2d_top, render2d); - - // Set up some overrides to turn off certain properties which we - // probably won't need for 2-d objects. - render2d_arc->set_transition(new DepthTestTransition(DepthTestProperty::M_none), 1); - render2d_arc->set_transition(new DepthWriteTransition(DepthWriteTransition::off()), 1); - render2d_arc->set_transition(new LightTransition(LightTransition::all_off()), 1); - render2d_arc->set_transition(new MaterialTransition(MaterialTransition::off()), 1); - render2d_arc->set_transition(new CullFaceTransition(CullFaceProperty::M_cull_none), 1); - - // Create a 2-d camera. - PT(Camera) cam2d = new Camera("cam2d"); - new RenderRelation(render2d, cam2d); - cam2d->set_scene(render2d_top); - - Frustumf frustum2d; - frustum2d.make_ortho_2D(); - cam2d->set_projection(OrthoProjection(frustum2d)); - - // Now create a new layer. - GraphicsChannel *chan = main_win->get_channel(0); - nassertv(chan != (GraphicsChannel *)NULL); - - GraphicsLayer *layer = chan->make_layer(); - nassertv(layer != (GraphicsLayer *)NULL); - - DisplayRegion *dr = layer->make_display_region(); - nassertv(dr != (DisplayRegion *)NULL); - dr->set_camera(cam2d); - - - // Put some interesting things in the 2-d scene graph. - PT_Node font = loader.load_sync("ttf-comic"); - - if (font != (NamedNode *)NULL) { - label2d = new TextNode("label2d"); - new RenderRelation(render2d, label2d); - - LMatrix4f mat = - LMatrix4f::scale_mat(0.1) * - LMatrix4f::translate_mat(0.0, 0.0, 0.8); - - label2d->set_transform(mat); - label2d->set_font(font.p()); - label2d->set_card_color(0.5, 0.5, 0.5, 0.5); - label2d->set_card_as_margin(0.5, 0.5, 0.2, 0.2); - label2d->set_frame_color(1.0, 1.0, 1.0, 1.0); - label2d->set_frame_as_margin(0.5, 0.5, 0.2, 0.2); - label2d->set_align(TM_ALIGN_CENTER); - label2d->set_text_color(0.2, 0.5, 1.0, 1.0); - label2d->set_text("Now presenting Panda 2-D!"); - - MouseWatcherRegion *region = - new MouseWatcherRegion("label2d", label2d->get_card_transformed()); - region->set_suppress_below(true); - mouse_watcher->add_region(region); - - } else { - nout << "Couldn't load font ttf-comic\n"; - } - - PT_Node p2egg = loader.load_sync("panda2d"); - if (p2egg != (NamedNode *)NULL) { - new RenderRelation(render2d, p2egg); - } else { - nout << "Couldn't find panda2d.egg\n"; - } - - // Load up a mouse cursor for fun. - PT_Node lilsmiley = loader.load_sync("lilsmiley"); - if (lilsmiley != (NamedNode *)NULL) { - NamedNode *n2 = new NamedNode("cursor"); - RenderRelation *s1_arc = new RenderRelation(render2d, n2); - RenderRelation *s2_arc = new RenderRelation(n2, lilsmiley); - - // Make up a scale to make it 32x32 pixels (it starts out 1x1 - // units). - LMatrix4f scale_mat = LMatrix4f::scale_mat(32.0 / main_win->get_width(), 1.0, 32.0 / main_win->get_height()); - s2_arc->set_transition(new TransformTransition(scale_mat)); - mouse_watcher->set_geometry(s1_arc); - } else { - nout << "Couldn't find lilsmiley.egg\n"; - } -} - -static void -event_in_label2d(CPT_Event) { - // The mouse moved over the label. - nassertv(!label2d.is_null()); - - label2d->set_card_color(0.8, 0.2, 1.0, 1.0); -} - -static void -event_out_label2d(CPT_Event) { - // The mouse moved out from the label. - nassertv(!label2d.is_null()); - - label2d->set_card_color(0.5, 0.5, 0.5, 0.5); -} -*/ - static void clear_highlight() { if (selected_node.has_arcs()) { diff --git a/panda/src/testbed/herc.cxx b/panda/src/testbed/herc.cxx index 984e26881d..60549a79fc 100644 --- a/panda/src/testbed/herc.cxx +++ b/panda/src/testbed/herc.cxx @@ -63,7 +63,7 @@ Configure(shader_test); ConfigureFn(shader_test) {} -PT(ProjectionNode) tex_proj; +PT(LensNode) tex_proj; PT(Trackball) tex_proj_trackball; PT(ProjtexShader) proj_shader; PT(ProjtexShadower) proj_shadow; @@ -405,7 +405,7 @@ void herc_keys(EventHandler &eh) { tex->set_name("smiley.rgba"); // Put the texture projector into the scene graph - tex_proj = new ProjectionNode("texture_projector"); + tex_proj = new LensNode("texture_projector"); RenderRelation* proj_arc = new RenderRelation(render, tex_proj); // Create a trackball to spin this around. @@ -430,8 +430,8 @@ void herc_keys(EventHandler &eh) { proj_shader->add_frustum(tex_proj); // Create a wireframe representation of the texture projector frustum - GeomLine* proj_geom = - (GeomLine *)tex_proj->get_projection()->make_geometry(); + PT(Geom) proj_geom = + tex_proj->get_lens()->make_geometry(); proj_geom_node = new GeomNode("proj_geometry"); proj_geom_node->add_geom(proj_geom); diff --git a/panda/src/testbed/min_herc.cxx b/panda/src/testbed/min_herc.cxx index 10400a0b56..110498f41a 100644 --- a/panda/src/testbed/min_herc.cxx +++ b/panda/src/testbed/min_herc.cxx @@ -59,7 +59,7 @@ //Math/Matrix/Vector/Transformation stuff #include #include -#include +#include #include //Control/IO @@ -75,7 +75,7 @@ Configure(min_herc); ConfigureFn(min_herc) { } -PT(ProjectionNode) tex_proj; +PT(LensNode) tex_proj; PT(Trackball) tex_proj_trackball; PT(ProjtexShader) proj_shader; PT(ProjtexShadower) proj_shadow; @@ -350,7 +350,7 @@ void herc_keys(EventHandler &eh) { tex->set_wrapv(Texture::WM_clamp); // Put the texture projector into the scene graph - tex_proj = new ProjectionNode("texture_projector"); + tex_proj = new LensNode("texture_projector"); RenderRelation* proj_arc = new RenderRelation(render, tex_proj); // Create a trackball to spin this around. @@ -375,8 +375,8 @@ void herc_keys(EventHandler &eh) { proj_shader->add_frustum(tex_proj); // Create a wireframe representation of the texture projector frustum - GeomLine* proj_geom = - (GeomLine *)tex_proj->get_projection()->make_geometry(); + PT(Geom) proj_geom = + tex_proj->get_lens()->make_geometry(); proj_geom_node = new GeomNode("proj_geometry"); proj_geom_node->add_geom(proj_geom); diff --git a/panda/src/testbed/min_shader.cxx b/panda/src/testbed/min_shader.cxx index 591384eb92..7f132b96b1 100644 --- a/panda/src/testbed/min_shader.cxx +++ b/panda/src/testbed/min_shader.cxx @@ -62,7 +62,7 @@ //Math/Matrix/Vector/Transformation stuff #include #include -#include +#include #include Configure(min_shader); @@ -70,7 +70,7 @@ ConfigureFn(min_shader) { } //--------Projective texture stuff-------- -PT(ProjectionNode) tex_proj; +PT(LensNode) tex_proj; PT(Trackball) tex_proj_trackball; PT(ProjtexShader) proj_shader; //--------Spotlight stuff----------------- @@ -551,7 +551,7 @@ void setup_projtex(void) // Create a projected texture shader // Put the texture projector into the scene graph - tex_proj = new ProjectionNode("texture_projector"); + tex_proj = new LensNode("texture_projector"); RenderRelation* proj_arc = new RenderRelation(render, tex_proj); // Create a trackball to spin this around. @@ -579,8 +579,8 @@ void setup_projtex(void) #define DISPLAY_TEXPROJFRUST #ifdef DISPLAY_TEXPROJFRUST // Display a wireframe representation of the texture projector frustum - GeomLine* proj_geom = - (GeomLine *)tex_proj->get_projection()->make_geometry(); + PT(Geom) proj_geom = + tex_proj->get_lens()->make_geometry(); GeomNode* proj_geom_node = new GeomNode("proj_geometry"); proj_geom_node->add_geom(proj_geom); RenderRelation *prr = new RenderRelation(tex_proj, proj_geom_node); @@ -599,10 +599,11 @@ void setup_spotlight(void) // Create a projected texture spotlight shader tex_proj_spot = new Spotlight("tex_proj_spotlight"); //Push out the far clipping plane of the spotlight frustum - Frustumf f; - f.make_perspective(45.0f, 45.0f, f._fnear, 13); - PerspectiveProjection pp(f); - tex_proj_spot->set_projection(pp); + PT(Lens) lens = new PerspectiveLens; + lens->set_fov(45.0f); + lens->set_near(f._fnear); + lens->set_far(13.0f); + tex_proj_spot->set_lens(lens); spot_arc = new RenderRelation(render, tex_proj_spot, 10); @@ -632,8 +633,8 @@ void setup_spotlight(void) #ifdef DISPLAY_TEXPROJSPOTFRUST // Display a wireframe representation of the spotlight frustum Colorf color_red(1., 0., 0., 1.); - GeomLine* frust_geom = - (GeomLine *)tex_proj_spot->get_projection()->make_geometry(color_red); + PT(Geom) frust_geom = + tex_proj_spot->get_lens()->make_geometry(); GeomNode* frust_geom_node = new GeomNode("frustum_geometry"); frust_geom_node->add_geom(frust_geom); RenderRelation *rr = new RenderRelation(tex_proj_spot, frust_geom_node); diff --git a/panda/src/testbed/panda.cxx b/panda/src/testbed/panda.cxx index 4d69c77987..eff82eb952 100644 --- a/panda/src/testbed/panda.cxx +++ b/panda/src/testbed/panda.cxx @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ PT(RenderRelation) hide_ball_arc; bool follow_ball; PT(PlanarSlider) ball_slider; -PT(ProjectionNode) tex_proj; +PT(LensNode) tex_proj; PT(ProjtexShader) proj_shader; PT(GeomNode) proj_geom_node; PT(Trackball) tex_proj_trackball; @@ -329,7 +329,7 @@ void setup_shaders(void) { // Projected texture shader Texture* tex = TexturePool::load_texture("smiley.rgba"); assert(tex != (Texture*)0L); - tex_proj = new ProjectionNode("texture_projector"); + tex_proj = new LensNode("texture_projector"); RenderRelation* proj_arc = new RenderRelation(root, tex_proj); tex_proj_trackball = new Trackball("tex_proj_trackball"); tex_proj_trackball->set_invert(false); @@ -346,8 +346,8 @@ void setup_shaders(void) { proj_arc->set_transition(new TransformTransition(proj_mat)); proj_shader = new ProjtexShader(tex); proj_shader->add_frustum(tex_proj); - GeomLine* proj_geom = - (GeomLine *)tex_proj->get_projection()->make_geometry(); + PT(Geom) proj_geom = + tex_proj->get_lens()->make_geometry(); proj_geom_node = new GeomNode("proj_geometry"); proj_geom_node->add_geom(proj_geom); proj_shader->set_priority(150); @@ -356,10 +356,11 @@ void setup_shaders(void) { // projected texture spotlight shader tex_proj_spot = new Spotlight("tex_proj_spotlight"); - Frustumf f; - f.make_perspective(45.0f, 45.0f, f._fnear, 13); - PerspectiveProjection pp(f); - tex_proj_spot->set_projection(pp); + PT(Lens) lens = new PerspectiveLens; + lens->set_fov(45.0f); + lens->set_near(f._fnear); + lens->set_far(13.0f); + tex_proj_spot->set_lens(lens); RenderRelation* spot_arc = new RenderRelation(root, tex_proj_spot, 10); tex_spot_trackball = new Trackball("tex_spot_trackball"); tex_spot_trackball->set_invert(false); diff --git a/panda/src/testbed/shader_test.cxx b/panda/src/testbed/shader_test.cxx index 35895658ef..db7139b3b0 100644 --- a/panda/src/testbed/shader_test.cxx +++ b/panda/src/testbed/shader_test.cxx @@ -62,7 +62,7 @@ Configure(shader_test); ConfigureFn(shader_test) { } -PT(ProjectionNode) tex_proj; +PT(LensNode) tex_proj; PT(Trackball) tex_proj_trackball; PT(ProjtexShader) proj_shader; PT(ProjtexShadower) proj_shadow; @@ -536,7 +536,7 @@ void shader_keys(EventHandler &eh) { tex->set_name("smiley.rgba"); // Put the texture projector into the scene graph - tex_proj = new ProjectionNode("texture_projector"); + tex_proj = new LensNode("texture_projector"); RenderRelation* proj_arc = new RenderRelation(render, tex_proj); // Create a trackball to spin this around. @@ -563,8 +563,8 @@ void shader_keys(EventHandler &eh) { #define DISPLAY_TEXPROJFRUST #ifdef DISPLAY_TEXPROJFRUST // Display a wireframe representation of the texture projector frustum - GeomLine* proj_geom = - (GeomLine *)tex_proj->get_projection()->make_geometry(); + PT(Geom) proj_geom = + tex_proj->get_lens()->make_geometry(); GeomNode* proj_geom_node = new GeomNode("proj_geometry"); //JMC: Removed _drawable_vector.push_back call and added add_geom //call @@ -603,8 +603,8 @@ void shader_keys(EventHandler &eh) { #ifdef DISPLAY_TEXPROJSPOTFRUST // Display a wireframe representation of the spotlight frustum Colorf color_red(1., 0., 0., 1.); - GeomLine* frust_geom = - (GeomLine *)tex_proj_spot->get_projection()->make_geometry(color_red); + PT(Geom) frust_geom = + tex_proj_spot->get_lens()->make_geometry(color_red); GeomNode* frust_geom_node = new GeomNode("frustum_geometry"); //JMC: Removed _drawable_vector.push_back call and added add_geom //call