2024-03-19 17:45:12 +08:00

198 lines
8.8 KiB
C++

/**************************************************************************************/
/* */
/* Visualization Library */
/* http://visualizationlibrary.org */
/* */
/* Copyright (c) 2005-2020, Michele Bosi */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without modification, */
/* are permitted provided that the following conditions are met: */
/* */
/* - Redistributions of source code must retain the above copyright notice, this */
/* list of conditions and the following disclaimer. */
/* */
/* - Redistributions in binary form must reproduce the above copyright notice, this */
/* list of conditions and the following disclaimer in the documentation and/or */
/* other materials provided with the distribution. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/**************************************************************************************/
#ifndef RayIntersector_INCLUDE_ONCE
#define RayIntersector_INCLUDE_ONCE
#include <vlCore/Ray.hpp>
#include <vlGraphics/Actor.hpp>
#include <vlGraphics/Geometry.hpp>
#include <vlCore/Vector4.hpp>
#include <vlCore/Matrix4.hpp>
#include <vlGraphics/Frustum.hpp>
namespace vl
{
class SceneManager;
//-----------------------------------------------------------------------------
// RayIntersection
//-----------------------------------------------------------------------------
/** The RayIntersection encapsulates all the information relative to a Ray/Actor intersection.
*/
class RayIntersection: public Object
{
VL_INSTRUMENT_CLASS(vl::RayIntersection, Object)
public:
RayIntersection(): mActor(NULL), mDistance(0.0f)
{
VL_DEBUG_SET_OBJECT_NAME()
}
//! The intersected Actor
void setActor(Actor* a) { mActor = a; }
//! The intersected Actor
const Actor* actor() const { return mActor; }
//! The intersected Actor
Actor* actor() { return mActor; }
//! The intersection point, in world coordinates
const vec3& intersectionPoint() const { return mIntersectionPoint; }
//! The intersection point, in world coordinates
void setIntersectionPoint(const vec3& v) { mIntersectionPoint = v; }
//! The intersection distance
real distance() const { return mDistance; }
//! The intersection distance
void setDistance(real dist) { mDistance = dist; }
protected:
vec3 mIntersectionPoint;
Actor* mActor;
real mDistance;
};
//-----------------------------------------------------------------------------
// RayIntersectionGeometry
//-----------------------------------------------------------------------------
/** The RayIntersectionGeometry encapsulates all the information relative to a Ray/Actor intersection,
providing also extra information relative to the intersection on the Geometry in use by the Actor. */
class RayIntersectionGeometry: public RayIntersection
{
VL_INSTRUMENT_CLASS(vl::RayIntersectionGeometry, RayIntersection)
public:
RayIntersectionGeometry(): mGeometry(NULL), mDrawCalls(NULL), mTriangleIndex(-1)
{
VL_DEBUG_SET_OBJECT_NAME()
memset(mTriangle, 0xFF, sizeof(mTriangle));
}
//! The intersected Geometry
Geometry* geometry() { return mGeometry; }
//! The intersected Geometry
const Geometry* geometry() const { return mGeometry; }
//! The intersected DrawCall
DrawCall* drawCalls() { return mDrawCalls; }
//! The intersected DrawCall
const DrawCall* drawCalls() const { return mDrawCalls; }
//! The starting index of the intersected primitive inside drawCalls()
int triangleIndex() const { return mTriangleIndex; }
//! An int[3] representing the indices of the intersected triangle.
const int* triangle() const { return mTriangle; }
//! The intersected Geometry
void setGeometry(Geometry* g) { mGeometry = g; }
//! The intersected DrawCall
void setPrimitives(DrawCall* p) { mDrawCalls = p; }
//! The starting index of the intersected primitive inside drawCalls()
void setTriangleIndex(int t_idx) { mTriangleIndex = t_idx; }
//! An int[3] representing the indices of the intersected triangle.
void setTriangle(int a, int b, int c) { mTriangle[0] = a; mTriangle[1] = b; mTriangle[2] = c; }
protected:
vec3 mIntersectionPoint;
Geometry* mGeometry;
DrawCall* mDrawCalls;
int mTriangleIndex;
int mTriangle[3];
float mDistance;
};
//-----------------------------------------------------------------------------
// RayIntersector
//-----------------------------------------------------------------------------
/** The RayIntersector class is used to detect the intersection points between a Ray and a set of Actor[s]
*/
class VLGRAPHICS_EXPORT RayIntersector: public Object
{
VL_INSTRUMENT_CLASS(vl::RayIntersector, Object)
public:
RayIntersector()
{
VL_DEBUG_SET_OBJECT_NAME()
mActors = new ActorCollection;
}
//! The Actors against which the intersection test is performed.
const ActorCollection* actors() const { return mActors.get(); }
//! The Actors against which the intersection test is performed.
ActorCollection* actors() { return mActors.get(); }
//! The ray in world coordinates to be intersected with the actors()
const Ray& ray() const { return mRay; }
//! The ray in world coordinates to be intersected with the actors()
void setRay(const Ray& ray) { mRay = ray; }
//! The frustum in world coordinates used to cull the objects.
const Frustum& frustum() const { return mFrustum; }
//! The frustum in world coordinates used to cull the objects.
void setFrustum(const Frustum& frustum) { mFrustum = frustum; }
//! The intersection points detected by the last intersect() call sorted according to their distance (the first one is the closest).
const std::vector< ref<RayIntersection> >& intersections() const { return mIntersections; }
/** Executes the intersection test.
* \note Before calling this function the transforms and the bounding volumes of the Actor[s] to be intersected must be updated, in this order.
* \note All the intersections are mande on the Actor's LOD level #0.
*/
void intersect();
/** Computes the intersections between the given ray and the Actor[s] contained in the given scene manager.
* This is an utility function equivalent to:
* \code
* intersector->actors()->clear();
* scene_manager->extractActors( *intersector->actors() );
* intersector->setRay(ray);
* intersector->intersect();
* \endcode
*/
void intersect(const Ray& ray, SceneManager* scene_manager);
protected:
static bool sorter(const ref<RayIntersection>& a, const ref<RayIntersection>& b) { return a->distance() < b->distance(); }
void intersect(Actor* act);
void intersectGeometry(Actor* act, Geometry* geom);
// T should be either fvec3-4 or dvec3-4
template<class T>
void intersectTriangle(const T& a, const T& b, const T& c, int ia, int ib, int ic, Actor*, Geometry* geom, DrawCall* prim, int prim_idx);
protected:
Frustum mFrustum;
std::vector< ref<RayIntersection> > mIntersections;
ref<ActorCollection> mActors;
Ray mRay;
};
}
#endif