From b286ad72749350bbfdd5619d2bf45847443d5fb8 Mon Sep 17 00:00:00 2001 From: Chris Laurel Date: Fri, 3 Dec 2010 02:07:08 +0000 Subject: [PATCH] Introduced 'multidraw' geometry that can extend across multiple depth intervals. This is currently used to prevent clipping of sensor geometry, but is a more generally useful feature. --- src/celengine/geometry.h | 12 ++++++ src/celengine/render.cpp | 76 +++++++++++++++++++++++++++++----- src/celengine/render.h | 27 +----------- src/celengine/sensorgeometry.h | 5 +++ 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/src/celengine/geometry.h b/src/celengine/geometry.h index d080fcd63..4cf3a64e6 100644 --- a/src/celengine/geometry.h +++ b/src/celengine/geometry.h @@ -53,6 +53,18 @@ public: virtual void loadTextures() { } + + /*! Return true if the geometry can be drawn multiple times in + * different depth ranges to avoid clipping and precision problems. + * Drawing multiple times is expensive, so this method should only + * return true for geometries that are simple and which need to + * be drawn correctly when the camera is positioned very close + * (relative to the size of the object.) + */ + virtual bool isMultidraw() const + { + return false; + } }; #endif // _CELENGINE_GEOMETRY_H_ diff --git a/src/celengine/render.cpp b/src/celengine/render.cpp index c77f6f29a..570f0751b 100644 --- a/src/celengine/render.cpp +++ b/src/celengine/render.cpp @@ -2848,6 +2848,7 @@ void Renderer::draw(const Observer& observer, // large enough to have discernible surface detail are also placed in // renderList. renderList.clear(); + multidrawRenderList.clear(); orbitPathList.clear(); lightSourceList.clear(); secondaryIlluminators.clear(); @@ -3464,10 +3465,34 @@ void Renderer::draw(const Observer& observer, nearZ = -nearZ * (float) cos(degToRad(fov / 2)) * ((float) windowHeight / maxSpan); #endif + // Handle multidraw items; these are placed into a separate list. Items in the multidraw + // list may be drawn in multiple depth intervals. + bool isMultidraw = false; + if (iter->renderableType == RenderListEntry::RenderableBody && iter->body->getGeometry() != InvalidResource) + { + Geometry* geom = GetGeometryManager()->find(iter->body->getGeometry()); + if (geom && geom->isMultidraw()) + { + isMultidraw = true; + } + } + if (nearZ > -MinNearPlaneDistance) - iter->nearZ = -max(MinNearPlaneDistance, radius / 2000.0f); + { + if (isMultidraw) + { + // No contraints on far/near ratio for multidraw items + iter->nearZ = -MinNearPlaneDistance; + } + else + { + iter->nearZ = -max(MinNearPlaneDistance, radius / 2000.0f); + } + } else + { iter->nearZ = nearZ; + } if (!convex) { @@ -3509,8 +3534,15 @@ void Renderer::draw(const Observer& observer, } } - *notCulled = *iter; - notCulled++; + if (isMultidraw) + { + multidrawRenderList.push_back(*iter); + } + else + { + *notCulled = *iter; + notCulled++; + } #ifdef USE_HDR if (iter->discSizeInPixels > 1.0f && iter->appMag < starMaxMag) @@ -3689,8 +3721,10 @@ void Renderer::draw(const Observer& observer, if (zNearest == prevNear) zNearest = 0.0f; - // Add one last interval for the span from 0 to the front of the - // nearest object + // Add intervals for the span from 0 to the front of the + // nearest object. Keep the far/near ratios of the intervals + // reasonable so that we don't end up with depth buffer precision + // problems when rendering multidraw items. { // TODO: closest object may not be at entry 0, since objects are // sorted by far distance. @@ -3708,13 +3742,19 @@ void Renderer::draw(const Observer& observer, } } - DepthBufferPartition partition; - partition.index = nIntervals; - partition.nearZ = closest; - partition.farZ = prevNear; - depthPartitions.push_back(partition); + while (prevNear < closest) + { + float n = std::min(closest, prevNear / 2000.0f); - nIntervals++; + DepthBufferPartition partition; + partition.index = nIntervals; + partition.nearZ = n; + partition.farZ = prevNear; + depthPartitions.push_back(partition); + nIntervals++; + + prevNear = n; + } } // If orbits are enabled, adjust the farthest partition so that it @@ -3816,6 +3856,20 @@ void Renderer::draw(const Observer& observer, i--; } + // Render all multidraw items + for (unsigned int j = 0; j < multidrawRenderList.size(); ++j) + { + const RenderListEntry& rle = multidrawRenderList[j]; + + if (rle.discSizeInPixels > 1.0f && rle.farZ < depthPartitions[interval].nearZ && rle.nearZ > depthPartitions[interval].farZ) + { + //if (nearPlaneDistance * 1000000 > farPlaneDistance) + { + renderItem(rle, observer, m_cameraOrientation, nearPlaneDistance, farPlaneDistance); + } + } + } + // Render orbit paths if (!orbitPathList.empty()) { diff --git a/src/celengine/render.h b/src/celengine/render.h index c560cd299..cfcc115fb 100644 --- a/src/celengine/render.h +++ b/src/celengine/render.h @@ -653,6 +653,7 @@ class Renderer PointStarVertexBuffer* pointStarVertexBuffer; PointStarVertexBuffer* glareVertexBuffer; std::vector renderList; + std::vector multidrawRenderList; std::vector secondaryIlluminators; std::vector depthPartitions; std::vector glareParticles; @@ -683,32 +684,6 @@ class Renderer int currentIntervalIndex; - - public: -#if 0 - struct OrbitSample - { - double t; - Point3d pos; - - OrbitSample(const Eigen::Vector3d& _pos, double _t) : t(_t), pos(_pos.x(), _pos.y(), _pos.z()) { } - OrbitSample() { } - }; - - struct OrbitSection - { - Capsuled boundingVolume; - uint32 firstSample; - }; - - struct CachedOrbit - { - std::vector trajectory; - std::vector sections; - uint32 lastUsed; - }; -#endif - private: typedef std::map OrbitCache; OrbitCache orbitCache; diff --git a/src/celengine/sensorgeometry.h b/src/celengine/sensorgeometry.h index fbd16313b..7a55c9360 100644 --- a/src/celengine/sensorgeometry.h +++ b/src/celengine/sensorgeometry.h @@ -37,6 +37,11 @@ class SensorGeometry : public Geometry virtual bool isOpaque() const; virtual bool isNormalized() const; + virtual bool isMultidraw() const + { + return true; + } + Body* observer() const { return m_observer;