/////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998-2011, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // 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. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // 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 // OWNER 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. // /////////////////////////////////////////////////////////////////////////// #include #include "PyImathDecorators.h" #include "PyImathExport.h" #include #include #include #include #include #include #include namespace PyImath{ using namespace boost::python; using namespace IMATH_NAMESPACE; template struct FrustumName {static const char *value;}; template <> const char *FrustumName::value = "Frustumf"; template <> const char *FrustumName::value = "Frustumd"; template struct FrustumTestName {static const char *value;}; template <> const char *FrustumTestName::value = "FrustumTestf"; template <> const char *FrustumTestName::value = "FrustumTestd"; template static std::string Frustum_repr(const Frustum &f) { std::stringstream stream; stream << FrustumName::value << "(" << f.nearPlane() << ", " << f.farPlane() << ", " << f.left() << ", " << f.right() << ", " << f.top() << ", " << f.bottom() << ", " << f.orthographic() << ")"; return stream.str(); } template static void modifyNearAndFar(Frustum &f, T nearPlane, T farPlane) { MATH_EXC_ON; f.modifyNearAndFar (nearPlane, farPlane); } template static T fovx(Frustum &f) { MATH_EXC_ON; return f.fovx(); } template static T fovy(Frustum &f) { MATH_EXC_ON; return f.fovy(); } template static T aspect(Frustum &f) { MATH_EXC_ON; return f.aspect(); } template static Matrix44 projectionMatrix(Frustum &f) { MATH_EXC_ON; return f.projectionMatrix(); } template static Frustum window (Frustum &f, T l, T r, T b, T t) { MATH_EXC_ON; return f.window(l, r, b, t); } template static Line3 projectScreenToRay (Frustum &f, const Vec2 &p) { MATH_EXC_ON; return f.projectScreenToRay(p); } template static Line3 projectScreenToRayTuple(Frustum &f, const tuple &t) { MATH_EXC_ON; if(t.attr("__len__")() == 2) { Vec2 point; point.x = extract(t[0]); point.y = extract(t[1]); return f.projectScreenToRay(point); } else THROW(IEX_NAMESPACE::LogicExc, "projectScreenToRay expects tuple of length 2"); } template static Vec2 projectPointToScreen (Frustum &f, const Vec3 &p) { MATH_EXC_ON; return f.projectPointToScreen(p); } template static Vec2 projectPointToScreenTuple(Frustum &f, const tuple &t) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 point; point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return f.projectPointToScreen(point); } else THROW(IEX_NAMESPACE::LogicExc, "projectPointToScreen expects tuple of length 3"); } template static Vec2 projectPointToScreenObj(Frustum &f, const object &o) { MATH_EXC_ON; Vec3 v; if (PyImath::V3::convert (o.ptr(), &v)) return f.projectPointToScreen(v); else THROW(IEX_NAMESPACE::LogicExc, "projectPointToScreen expects tuple of length 3"); } template static T ZToDepth(Frustum &f, long z, long min, long max) { MATH_EXC_ON; return f.ZToDepth(z, min, max); } template static T normalizedZToDepth(Frustum &f, T z) { MATH_EXC_ON; return f.normalizedZToDepth(z); } template static long DepthToZ(Frustum &f, T depth, long min, long max) { MATH_EXC_ON; return f.DepthToZ(depth, min, max); } template static T worldRadius(Frustum &f, const Vec3 &p, T radius) { MATH_EXC_ON; return f.worldRadius(p, radius); } template static T worldRadiusTuple(Frustum &f, const tuple &t, T radius) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 point; point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return f.worldRadius(point, radius); } else THROW(IEX_NAMESPACE::LogicExc, "worldRadius expects tuple of length 3"); } template static T screenRadius(Frustum &f, const Vec3 &p, T radius) { MATH_EXC_ON; return f.screenRadius(p, radius); } template static T screenRadiusTuple(Frustum &f, const tuple &t, T radius) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 point; point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return f.screenRadius(point, radius); } else THROW(IEX_NAMESPACE::LogicExc, "screenRadius expects tuple of length 3"); } template static void planes1(Frustum &f, Plane3 *p) { MATH_EXC_ON; f.planes(p); } template static void planes2(Frustum &f, Plane3 *p, const Matrix44 &m) { MATH_EXC_ON; f.planes(p, m); } template static tuple planes3(Frustum &f, const Matrix44 &mat) { MATH_EXC_ON; IMATH_NAMESPACE::Plane3 p[6]; f.planes(p,mat); tuple t = make_tuple(p[0],p[1],p[2],p[3],p[4],p[5]); return t; } template static tuple planes4(Frustum &f) { MATH_EXC_ON; IMATH_NAMESPACE::Plane3 p[6]; f.planes(p); tuple t = make_tuple(p[0],p[1],p[2],p[3],p[4],p[5]); return t; } template class_ > register_Frustum() { void (IMATH_NAMESPACE::Frustum::*set1)(T,T,T,T,T,T,bool) = &IMATH_NAMESPACE::Frustum::set; void (IMATH_NAMESPACE::Frustum::*set2)(T,T,T,T,T) = &IMATH_NAMESPACE::Frustum::set; const char *name = FrustumName::value; class_< Frustum > frustum_class(name,name,init >("copy construction")); frustum_class .def(init<>("Frustum() default construction")) .def(init("Frustum(nearPlane,farPlane,left,right,top,bottom,ortho) construction")) .def(init("Frustum(nearPlane,farPlane,fovx,fovy,aspect) construction")) .def(self == self) .def(self != self) .def("__repr__",&Frustum_repr) .def("set", set1, "F.set(nearPlane, farPlane, left, right, top, bottom, " "[ortho])\n" "F.set(nearPlane, farPlane, fovx, fovy, aspect) " " -- sets the entire state of " "frustum F as specified. Only one of " "fovx or fovy may be non-zero.") .def("set", set2) .def("modifyNearAndFar", &modifyNearAndFar, "F.modifyNearAndFar(nearPlane, farPlane) -- modifies " "the already-valid frustum F as specified") .def("setOrthographic", &Frustum::setOrthographic, "F.setOrthographic(b) -- modifies the " "already-valid frustum F to be orthographic " "or not") .def("nearPlane", &Frustum::nearPlane, "F.nearPlane() -- returns the coordinate of the " "near clipping plane of frustum F") .def("farPlane", &Frustum::farPlane, "F.farPlane() -- returns the coordinate of the " "far clipping plane of frustum F") // The following two functions provide backwards compatibility // with the previous API for this class. .def("near", &Frustum::nearPlane, "F.near() -- returns the coordinate of the " "near clipping plane of frustum F") .def("far", &Frustum::farPlane, "F.far() -- returns the coordinate of the " "far clipping plane of frustum F") .def("left", &Frustum::left, "F.left() -- returns the left coordinate of " "the near clipping window of frustum F") .def("right", &Frustum::right, "F.right() -- returns the right coordinate of " "the near clipping window of frustum F") .def("top", &Frustum::top, "F.top() -- returns the top coordinate of " "the near clipping window of frustum F") .def("bottom", &Frustum::bottom, "F.bottom() -- returns the bottom coordinate " "of the near clipping window of frustum F") .def("orthographic", &Frustum::orthographic, "F.orthographic() -- returns whether frustum " "F is orthographic or not") .def("planes", planes1, "F.planes([M]) -- returns a sequence of 6 " "Plane3s, the sides of the frustum F " "(top, right, bottom, left, nearPlane, farPlane), " "optionally transformed by the matrix M " "if specified") .def("planes", planes2) .def("planes", planes3) .def("planes", planes4) .def("fovx", &fovx, "F.fovx() -- derives and returns the " "x field of view (in radians) for frustum F") .def("fovy", &fovy, "F.fovy() -- derives and returns the " "y field of view (in radians) for frustum F") .def("aspect", &aspect, "F.aspect() -- derives and returns the " "aspect ratio for frustum F") .def("projectionMatrix", &projectionMatrix, "F.projectionMatrix() -- derives and returns " "the projection matrix for frustum F") .def("window", &window, "F.window(l,r,b,t) -- takes a rectangle in " "the screen space (i.e., -1 <= l <= r <= 1, " "-1 <= b <= t <= 1) of F and returns a new " "Frustum whose near clipping-plane window " "is that rectangle in local space") .def("projectScreenToRay", &projectScreenToRay, "F.projectScreenToRay(V) -- returns a Line3 " "through V, a V2 point in screen space") .def("projectScreenToRay", &projectScreenToRayTuple) .def("projectPointToScreen", &projectPointToScreen, "F.projectPointToScreen(V) -- returns the " "projection of V3 V into screen space") .def("projectPointToScreen", &projectPointToScreenTuple) .def("projectPointToScreen", &projectPointToScreenObj) .def("ZToDepth", &ZToDepth, "F.ZToDepth(z, zMin, zMax) -- returns the " "depth (Z in the local space of the " "frustum F) corresponding to z (a result of " "transformation by F's projection matrix) " "after normalizing z to be between zMin " "and zMax") .def("normalizedZToDepth", &normalizedZToDepth, "F.normalizedZToDepth(z) -- returns the " "depth (Z in the local space of the " "frustum F) corresponding to z (a result of " "transformation by F's projection matrix), " "which is assumed to have been normalized " "to [-1, 1]") .def("DepthToZ", &DepthToZ, "F.DepthToZ(depth, zMin, zMax) -- converts " "depth (Z in the local space of the frustum " "F) to z (a result of transformation by F's " "projection matrix) which is normalized to " "[zMin, zMax]") .def("worldRadius", &worldRadius, "F.worldRadius(V, r) -- returns the radius " "in F's local space corresponding to the " "point V and radius r in screen space") .def("worldRadius", &worldRadiusTuple) .def("screenRadius", &screenRadius, "F.screenRadius(V, r) -- returns the radius " "in screen space corresponding to " "the point V and radius r in F's local " "space") .def("screenRadius", &screenRadiusTuple) ; decoratecopy(frustum_class); return frustum_class; } template struct IsVisibleTask : public Task { const IMATH_NAMESPACE::FrustumTest& frustumTest; const PyImath::FixedArray& points; PyImath::FixedArray& results; IsVisibleTask(const IMATH_NAMESPACE::FrustumTest& ft, const PyImath::FixedArray &p, PyImath::FixedArray &r) : frustumTest(ft), points(p), results(r) {} void execute(size_t start, size_t end) { for(size_t p = start; p < end; ++p) results[p] = frustumTest.isVisible(IMATH_NAMESPACE::Vec3(points[p])); } }; template PyImath::FixedArray frustumTest_isVisible(IMATH_NAMESPACE::FrustumTest& ft, const PyImath::FixedArray& points) { size_t numPoints = points.len(); PyImath::FixedArray mask(numPoints); IsVisibleTask task(ft,points,mask); dispatchTask(task,numPoints); return mask; } template class_ > register_FrustumTest() { const char *name = FrustumTestName::value; bool (FrustumTest::*isVisibleS)(const Sphere3 &) const = &FrustumTest::isVisible; bool (FrustumTest::*isVisibleB)(const Box > &) const = &FrustumTest::isVisible; bool (FrustumTest::*isVisibleV)(const Vec3 &) const = &FrustumTest::isVisible; bool (FrustumTest::*completelyContainsS)(const Sphere3 &) const = &FrustumTest::completelyContains; bool (FrustumTest::*completelyContainsB)(const Box > &) const = &FrustumTest::completelyContains; class_< FrustumTest > frustumtest_class(name,name,init&,const IMATH_NAMESPACE::Matrix44&>("create a frustum test object from a frustum and transform")); frustumtest_class .def("isVisible",isVisibleS) .def("isVisible",isVisibleB) .def("isVisible",isVisibleV) .def("isVisible",&frustumTest_isVisible) .def("completelyContains",completelyContainsS) .def("completelyContains",completelyContainsB) ; decoratecopy(frustumtest_class); return frustumtest_class; } template PYIMATH_EXPORT class_ > register_Frustum(); template PYIMATH_EXPORT class_ > register_Frustum(); template PYIMATH_EXPORT class_ > register_FrustumTest(); template PYIMATH_EXPORT class_ > register_FrustumTest(); }