/*
Copyright (C) 2010, Heikki Salo
All rights reserved.
Distributed under the BSD license:
http://www.opensource.org/licenses/bsd-license.php
*/
#include "stdafx.h"
#include "DPVector.hpp"
#include "DPMatrix.hpp"
python::str DPVector::str()
{
std::ostringstream ss;
ss << std::fixed << "Vector(" << get_x() << ", " << get_y() << ", " << get_z() << ")";
return python::str(ss.str().c_str());
}
DPVector DPVector::project(python::object& viewport, const DPMatrix& proj,
const DPMatrix& view, const DPMatrix& world)
{
XMVECTOR temp = XMVector3Project(vector,
python::extract<float>(viewport[0]),
python::extract<float>(viewport[1]),
python::extract<float>(viewport[2]),
python::extract<float>(viewport[3]),
python::extract<float>(viewport[4]),
python::extract<float>(viewport[5]),
proj.getMatrix(),
view.getMatrix(),
world.getMatrix());
return DPVector(temp);
}
DPVector DPVector::unproject(python::object& viewport, const DPMatrix& proj,
const DPMatrix& view, const DPMatrix& world)
{
XMVECTOR temp = XMVector3Unproject(vector,
python::extract<float>(viewport[0]),
python::extract<float>(viewport[1]),
python::extract<float>(viewport[2]),
python::extract<float>(viewport[3]),
python::extract<float>(viewport[4]),
python::extract<float>(viewport[5]),
proj.getMatrix(),
view.getMatrix(),
world.getMatrix());
return DPVector(temp);
}
DPVector VCatmullRom(python::object& v1, python::object& v2, python::object& v3, python::object& v4, float s)
{
return XMVectorCatmullRom(PyToXMV(v1), PyToXMV(v2), PyToXMV(v3), PyToXMV(v4), s);
}
DPVector VHermite(python::object& v1, python::object& t1, python::object& v2, python::object& t2, float s)
{
return XMVectorHermite(PyToXMV(v1), PyToXMV(t1), PyToXMV(v2), PyToXMV(t2), s);
}
DPVector triNormal(const python::object& aArg, const python::object& bArg, const python::object& cArg)
{
XMVECTOR a = PyToXMV(aArg);
XMVECTOR b = PyToXMV(bArg);
XMVECTOR c = PyToXMV(cArg);
XMVECTOR u = XMVectorSubtract(b, a);
XMVECTOR v = XMVectorSubtract(c, b);
XMVECTOR cross = XMVector3Cross(u, v);
return XMVector3Normalize(cross);
}
/*
Fast, Minimum Storage Ray-Triangle Intersection (non-culling version)
http://jgt.akpeters.com/papers/MollerTrumbore97/
-Tomas Möller
-Ben Trumbore
*/
#define INTERSECT_EPSILON 0.000001f
python::object triIntersect(const python::object& aArg, const python::object& bArg, const python::object& cArg,
const python::object& posArg, const python::object& dirArg)
{
XMVECTOR vert0 = PyToXMV(aArg);
XMVECTOR vert1 = PyToXMV(bArg);
XMVECTOR vert2 = PyToXMV(cArg);
XMVECTOR orig = PyToXMV(posArg);
XMVECTOR dir = PyToXMV(dirArg);
XMVECTOR edge1, edge2, tvec, pvec, qvec;
//Find vectors for two edges sharing vert0
edge1 = XMVectorSubtract(vert1, vert0);
edge2 = XMVectorSubtract(vert2, vert0);
//Begin calculating determinant - also used to calculate U parameter
pvec = XMVector3Cross(dir, edge2);
//If determinant is near zero, ray lies in plane of triangle
const float det = XMVectorGetX(XMVector3Dot(edge1, pvec));
if (det > -INTERSECT_EPSILON && det < INTERSECT_EPSILON)
return python::object();
const float inv_det = 1.0f / det;
//Calculate distance from vert0 to ray origin
tvec = XMVectorSubtract(orig, vert0);
//Calculate U parameter and test bounds
const float u = XMVectorGetX(XMVector3Dot(tvec, pvec)) * inv_det;
if (u < 0.0f || u > 1.0f)
return python::object();
//Prepare to test V parameter
qvec = XMVector3Cross(tvec, edge1);
//Calculate V parameter and test bounds
const float v = XMVectorGetX(XMVector3Dot(dir, qvec)) * inv_det;
if (v < 0.0f || u + v > 1.0f)
return python::object();
//Calculate t, ray intersects triangle
const float t = XMVectorGetX(XMVector3Dot(edge2, qvec)) * inv_det;
//Done, compute the final result.
const float buv = 1.0f - (u + v);
XMVECTOR res1 = XMVectorMultiply(vert0, XMVectorReplicate(buv));
XMVECTOR res2 = XMVectorMultiply(vert1, XMVectorReplicate(u));
XMVECTOR res3 = XMVectorMultiply(vert2, XMVectorReplicate(v));
XMVECTOR result = XMVectorAdd(XMVectorAdd(res1, res2), res3);
return python::object(DPVector(result));
}
struct DPVectorPickleSuite : python::pickle_suite {
static python::tuple getinitargs(DPVector const& v) {
return python::make_tuple(v.get_x(), v.get_y(), v.get_z(), v.get_w());
}
};
void ExportDPVector()
{
using namespace boost::python;
class_<DPVector>("Vector")
.def(init<float, float, float>())
.def(init<float, float, float, float>())
.def(init<const DPVector&>())
.def(init<object&>())
.def("angle", &DPVector::angle)
.def("direction", &DPVector::direction)
.def("distance", &DPVector::distance)
.def("distanceLine", &DPVector::distanceLine)
.def("length", &DPVector::length)
.def("dot", &DPVector::dot)
.def("cross", &DPVector::cross)
.def("lerp", &DPVector::lerp)
.def("normalize", &DPVector::normalize)
.def("project", &DPVector::project)
.def("unproject", &DPVector::unproject)
.def("reflect", &DPVector::reflect)
.def("splineCatmullRom", &VCatmullRom).staticmethod("splineCatmullRom")
.def("splineHermite", &VHermite).staticmethod("splineHermite")
.def("triNormal", &triNormal).staticmethod("triNormal")
.def("triIntersect", &triIntersect).staticmethod("triIntersect")
.add_property("x", &DPVector::get_x, &DPVector::set_x)
.add_property("y", &DPVector::get_y, &DPVector::set_y)
.add_property("z", &DPVector::get_z, &DPVector::set_z)
.add_property("w", &DPVector::get_w, &DPVector::set_w)
.def("__str__", &DPVector::str)
.def("__repr__", &DPVector::str)
.def("__getitem__", &DPVector::getitem)
.def("__len__", &DPVector::len)
.def_pickle(DPVectorPickleSuite())
.def("__neg__", &DPVector::operator_neg_)
.def(self * float())
.def(self *= float())
.def("__truediv__", &DPVector::operator_truediv_)
.def("__itruediv__", &DPVector::operator_itruediv_, return_self<>())
.def(self / float())
.def(self /= float())
.def(self + self)
.def(self += self)
.def(self - self)
.def(self -= self)
//.def(self == self)
;
}