#ifndef _GvsPreprocessor_H__ #define _GvsPreprocessor_H__ #include #include #include "Preprocessor.h" namespace GtpVisibilityPreprocessor { class Exporter; class VssRay; class TriangleIntersectable; class KdIntersectable; class ViewCellBasedDistribution; class ViewCellBorderBasedDistribution; /** View space partition statistics. */ class GvsStatistics: public StatisticsBase { public: /// Constructor GvsStatistics() { Reset(); } void Reset() { mPass = 0; mTotalSamples = 0; mPassContribution = 0; mTotalContribution = 0; mReverseSamples = 0; mBorderSamples = 0; mGvsRuns = 0; mRandomSamples = 0; mGvsSamples = 0; mTotalPvs = 0; mViewCells = 0; mPerViewCellSamples = 0; mPerViewCellPvs = 0; mTrianglePvs = 0; mViewCellId = 0; mTotalTime = 0; mTimePerViewCell = 0; mTotalTrianglePvs = 0; mPvsCost = 0; } public: int mRandomSamples; int mGvsSamples; int mPass; int mTotalSamples; int mPassContribution; int mTotalContribution; int mReverseSamples; int mBorderSamples; int mGvsRuns; int mTotalPvs; int mViewCells; int mPerViewCellSamples; int mPerViewCellPvs; int mTrianglePvs; int mTotalTrianglePvs; int mViewCellId; float mTimePerViewCell; float mTotalTime; float mPvsCost; ObjectContainer mKdPvs; float RaysPerSec() const { if (!mTotalTime) return 0; return (float)(mTotalSamples / mTotalTime) * 1e-6f; } void Print(ostream &app) const; friend ostream &operator<<(ostream &s, const GvsStatistics &stat) { stat.Print(s); return s; } }; /** Sampling based visibility preprocessing. The implementation is based on heuristical sampling of view space. */ class GvsPreprocessor : public Preprocessor { public: GvsPreprocessor(); ~GvsPreprocessor(); virtual bool ComputeVisibility(); protected: #if 0 struct PendingRay { PendingRay(VssRay *ray, const bool d) : mRay(ray), mFoundDiscontinuity(d) {} VssRay *mRay; bool mFoundDiscontinuity; }; typedef stack PendingQueue; #endif typedef stack RayQueue; /** Runs the adaptive sampling until the ray queue is empty. The method starts with a number of random rays given by the queue and continues as long it finds new visible geometry (i.e., the queue is not empty). @returns the number of samples cast. */ int ProcessQueue(); /** Generates the rays starting the adaptive visibility sampling process. */ int CastInitialSamples(int numSamples); /** Uses the information gained from the ray for doing adaptive border sampling. This function tries to find the border of the triangle found visible by the current ray. New rays are generated which sample this border. We use the following strategies: a) if new triangle was found: adaptive border sampling b) if triangle was found reverse sampling */ inline bool HandleRay(VssRay *ray); /** The adaptive border sampling step. It aims to find neighbouring triangles of the one hit by the current ray. */ int AdaptiveBorderSampling(const VssRay ¤tRay); int AdaptiveBorderSamplingOpt(const VssRay ¤tRay); /** The reverse sampling step. It is started once the cast ray finds a discontinuity, i.e., a closer triangle. Then the process tries to find a ray from the old triangle passing through a gap. */ bool ComputeReverseRay(const VssRay ¤tRay, const Triangle3 &hitTriangle, const VssRay &oldRay, SimpleRay &reverseRay); /** Returns true if we sampled a closer triangle than with the previous ray. Does reverse sampling if gap found. */ int CheckDiscontinuity(const VssRay ¤tRay, const Triangle3 &hitTriangle, const VssRay &oldRay); /** Adds new samples to the ray queue and classifies them with respect to the previous ray. */ void EnqueueRays(VssRayContainer &samples); /** Hepler function for adaptive border sampling. It finds new sample points around a triangle in a eps environment */ void EnlargeTriangle(VertexContainer &vertices, const Triangle3 &hitTriangle, const VssRay &ray) const; int SubdivideEdge(const Triangle3 &hitTriangle, const Vector3 &p1, const Vector3 &p2, const VssRay &ray1, const VssRay &ray2, const VssRay &oldRay); void Visualize(); void CreateDisplacedVertices(VertexContainer &vertices, const Triangle3 &hitTriangle, const VssRay &ray, const int index) const; Vector3 CalcPredictedHitPoint(const VssRay &newRay, const Triangle3 &hitTriangle, const VssRay &oldRay) const; bool GetPassingPoint(const VssRay ¤tRay, const Triangle3 &occluder, const VssRay &oldRay, Vector3 &newPoint) const; ViewCell *NextViewCell(); void GlobalComputation(); /** Loops over aall view cellls. */ void PerViewCellComputation(); void PerViewCellComputation2(); void VisualizeViewCells(); void VisualizeViewCell(ViewCell *vc); void VisualizeViewCell(const ObjectContainer &objects); /** Exchanges view cell triangle pvs with bvh leaf pvs. */ void UpdatePvs(ViewCell *currentViewCell); void ClearRayQueue(); /** Create a list of view cells gvs is run on. */ void CompileViewCellsList(); void GetObjectPvs(ObjectContainer &trianglePvs) const; bool HasContribution(VssRay &ray); void ComputeViewCellGeometryIntersection(); void DeterminePvsObjects(VssRayContainer &rays); void StorePvs(const ObjectContainer &objectPvs); /** Compute visibility for the current view cell using gvs */ void ComputeViewCell(); /** Use this for qt visualization. */ void UpdateStatsForVisualization(KdIntersectable *kdInt); void CompileViewCellsFromPointList(); void ComputeStats(); int ConvertObjectPvs(); /** Keep count of new objects for stats. Returns number of new pvs entries. */ inline int CountObject(Intersectable *triObj); inline bool AddTriangleObject(Intersectable *triObj); inline void AddKdNodeToPvs(const Vector3 &termination); /** For all rayys of the ray container, generates a ray bundle of 4 jittered rays and casts them using optimized 4 eye ray casting. */ void CastRayBundles4(const SimpleRayContainer &rays, VssRayContainer &vssRays); void CastRayBundles16(const SimpleRayContainer &rays, VssRayContainer &vssRays); /** Generates a ray bundle of 4 jittered rays and casts them using optimized 4 eye ray casting. */ void CastRayBundle4(const SimpleRay &ray, VssRayContainer &vssRays, const AxisAlignedBox3 &box); /** Cast rays using the optimized 4 eye ray casting routine. */ void CastRays4(const SimpleRayContainer &rays, VssRayContainer &vssRays); /** Wrapper for optized ray casting routine taking 4 eye rays and a bounding box for ray clipping. */ void Cast4Rays(float *dist, Vector3 *dirs, Vector3 *origs, VssRayContainer &vssRays, const AxisAlignedBox3 &box); void CastRayBundle16(const SimpleRay &ray, VssRayContainer &vssRays); virtual void ComputeRenderError(); bool GenerateImportanceSample(const VssRay &ray, const Triangle3 &triangle, SimpleRay &sray); void GenerateImportanceSamples(const VssRay &ray, const Triangle3 &triangle, int numSamples, SimpleRayContainer &simpleRays); /** Collects triangles which are probably visible. Warning: returns only unmailed objects. */ void CollectProbablyVisibleTriangles(ObjectContainer &triangles); void PrepareProbablyVisibleSampling(); ////////////////////// bool mUseKdPvs; int mInitialSamples; RayQueue mRayQueue; ViewCellBasedDistribution *mDistribution; //AxisAlignedBox3 mViewSpaceBox; float mEps; float mThreshold; VssRayContainer mVssRays; ObjectContainer mKdPvs; /////////// // stats ofstream mGvsStatsStream; GvsStatistics mGvsStats; bool mPerViewCell; bool mOnlyRandomSampling; ViewCell *mCurrentViewCell; int mProcessedViewCells; int mMinContribution; ViewCellContainer mViewCells; int mMaxViewCells; int mGvsSamplesPerPass; bool mComputeRenderError; bool mEvaluatePixelError; Vector3 mCurrentViewPoint; /// container for probably visible triangles ObjectContainer mProbablyVisibleTriangles; bool mUseProbablyVisibleSampling; }; }; #endif