|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
|
|
|
|
|
Vladimír Vondruš <mosra@centrum.cz>
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
to deal in the Software without restriction, including without limitation
|
|
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "magnum/math.vector.h"
|
|
|
|
|
|
|
|
|
|
namespace magnum {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
template<class T> void vectorFloat(py::module& m, py::class_<T>& c) {
|
|
|
|
|
m
|
|
|
|
|
.def("angle", [](const T& a, const T& b) { return Radd(Math::angle(a, b)); },
|
|
|
|
|
"Angle between normalized vectors", py::arg("normalized_a"), py::arg("normalized_b"));
|
|
|
|
|
|
|
|
|
|
c
|
|
|
|
|
.def("is_normalized", &T::isNormalized, "Whether the vector is normalized")
|
|
|
|
|
.def("length", &T::length, "Vector length")
|
|
|
|
|
|
|
|
|
|
/* Cast needed because these are enabled only for floats */
|
|
|
|
|
.def("length_inverted", static_cast<typename T::Type(T::*)() const>(&T::lengthInverted), "Inverse vector length")
|
|
|
|
|
.def("normalized", static_cast<T(T::*)() const>(&T::normalized),
|
|
|
|
|
"Normalized vector (of unit length)")
|
|
|
|
|
.def("resized", static_cast<T(T::*)(typename T::Type) const>(&T::resized),
|
|
|
|
|
"Resized vector")
|
|
|
|
|
.def("projected", [](const T& self, const T& line) {
|
|
|
|
|
return self.projected(line);
|
|
|
|
|
}, "Vector projected onto a line")
|
|
|
|
|
.def("projected_onto_normalized", [](const T& self, const T& line) {
|
|
|
|
|
return self.projectedOntoNormalized(line);
|
|
|
|
|
}, "Vector projected onto a normalized line");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T> void vectorsFloat(py::module& m, py::class_<Math::Vector2<T>>& vector2_, py::class_<Math::Vector3<T>>& vector3_, py::class_<Math::Vector4<T>>& vector4_) {
|
|
|
|
|
vector2_
|
|
|
|
|
.def("aspect_ratio", static_cast<T(Math::Vector2<T>::*)() const>(&Math::Vector2<T>::aspectRatio),
|
|
|
|
|
"Aspect ratio")
|
|
|
|
|
.def("cross", static_cast<T(*)(const Math::Vector2<T>&, const Math::Vector2<T>&)>(Math::cross),
|
|
|
|
|
"2D cross product");
|
|
|
|
|
everyVector(vector2_);
|
|
|
|
|
vector<Math::Vector2<T>>(m, vector2_);
|
|
|
|
|
vectorFloat<Math::Vector2<T>>(m, vector2_);
|
|
|
|
|
vector2<T>(vector2_);
|
|
|
|
|
|
|
|
|
|
vector3_
|
|
|
|
|
.def("cross", static_cast<Math::Vector3<T>(*)(const Math::Vector3<T>&, const Math::Vector3<T>&)>(Math::cross),
|
|
|
|
|
"Cross product");
|
|
|
|
|
everyVector(vector3_);
|
|
|
|
|
vector<Math::Vector3<T>>(m, vector3_);
|
|
|
|
|
vectorFloat<Math::Vector3<T>>(m, vector3_);
|
|
|
|
|
vector3<T>(vector3_);
|
|
|
|
|
|
|
|
|
|
everyVector(vector4_);
|
|
|
|
|
vector<Math::Vector4<T>>(m, vector4_);
|
|
|
|
|
vectorFloat<Math::Vector4<T>>(m, vector4_);
|
|
|
|
|
vector4<T>(vector4_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mathVectorFloat(py::module& root, py::module& m) {
|
python: implement buffer protocol for Vector types as well.
This makes Vector3 to np.array conversion about 20x faster. Yes, *that*
much. Crazy. Timings from the benchmark added in previous commit before:
np.array([]) 0.66096 µs
np.array([1.0, 2.0, 3.0]) 0.70623 µs
a = array.array("f", [1.0, 2.0, 3.0]); np.array(a) 0.57877 µs
a = Vector3(1.0, 2.0, 3.0); np.array(a) 18.18542 µs
after:
np.array([]) 0.57162 µs
np.array([1.0, 2.0, 3.0]) 0.68309 µs
a = array.array("f", [1.0, 2.0, 3.0]); np.array(a) 0.53958 µs
a = Vector3(1.0, 2.0, 3.0); np.array(a) 0.74818 µs
There's still some overhead that could be removed I think, making the
Vector3-to-numpy conversion faster than list-to-numpy.
7 years ago
|
|
|
py::class_<Vector2> vector2{root, "Vector2", "Two-component float vector", py::buffer_protocol{}};
|
|
|
|
|
py::class_<Vector3> vector3{root, "Vector3", "Threee-component float vector", py::buffer_protocol{}};
|
|
|
|
|
py::class_<Vector4> vector4{root, "Vector4", "Four-component float vector", py::buffer_protocol{}};
|
|
|
|
|
py::class_<Vector2d> vector2d{root, "Vector2d", "Two-component double vector", py::buffer_protocol{}};
|
|
|
|
|
py::class_<Vector3d> vector3d{root, "Vector3d", "Threee-component double vector", py::buffer_protocol{}};
|
|
|
|
|
py::class_<Vector4d> vector4d{root, "Vector4d", "Four-component double vector", py::buffer_protocol{}};
|
|
|
|
|
vectorsFloat<Float>(m, vector2, vector3, vector4);
|
|
|
|
|
vectorsFloat<Double>(m, vector2d, vector3d, vector4d);
|
|
|
|
|
|
|
|
|
|
/* The subclasses don't have buffer protocol enabled, as that's already
|
|
|
|
|
done by the base classes. Moreover, just adding py::buffer_protocol{}
|
|
|
|
|
would cause it to not find the buffer functions as we don't add them
|
|
|
|
|
anywhere, thus failing with `pybind11_getbuffer(): Internal error`. */
|
|
|
|
|
|
|
|
|
|
py::class_<Color3, Vector3> color3_{root, "Color3", "Color in linear RGB color space"};
|
|
|
|
|
everyVector(color3_);
|
|
|
|
|
color(color3_);
|
|
|
|
|
color3(color3_);
|
|
|
|
|
|
|
|
|
|
py::class_<Color4, Vector4> color4_{root, "Color4", "Color in linear RGBA color space"};
|
|
|
|
|
everyVector(color4_);
|
|
|
|
|
color(color4_);
|
|
|
|
|
color4(color4_);
|
|
|
|
|
|
|
|
|
|
/* Register the integer types as well, only after that register type
|
|
|
|
|
conversions because they need all the types */
|
|
|
|
|
mathVectorIntegral(root, m);
|
|
|
|
|
|
|
|
|
|
convertible(vector2);
|
|
|
|
|
convertible(vector3);
|
|
|
|
|
convertible(vector4);
|
|
|
|
|
convertible(vector2d);
|
|
|
|
|
convertible(vector3d);
|
|
|
|
|
convertible(vector4d);
|
|
|
|
|
/* Colors are float-only at the moment, thus no conversions */
|
python: implement buffer protocol for Vector types as well.
This makes Vector3 to np.array conversion about 20x faster. Yes, *that*
much. Crazy. Timings from the benchmark added in previous commit before:
np.array([]) 0.66096 µs
np.array([1.0, 2.0, 3.0]) 0.70623 µs
a = array.array("f", [1.0, 2.0, 3.0]); np.array(a) 0.57877 µs
a = Vector3(1.0, 2.0, 3.0); np.array(a) 18.18542 µs
after:
np.array([]) 0.57162 µs
np.array([1.0, 2.0, 3.0]) 0.68309 µs
a = array.array("f", [1.0, 2.0, 3.0]); np.array(a) 0.53958 µs
a = Vector3(1.0, 2.0, 3.0); np.array(a) 0.74818 µs
There's still some overhead that could be removed I think, making the
Vector3-to-numpy conversion faster than list-to-numpy.
7 years ago
|
|
|
|
|
|
|
|
/* This needs to be *after* conversion constructors so the type conversion
|
|
|
|
|
gets picked before the general buffer constructor (which would then
|
|
|
|
|
fail) */
|
|
|
|
|
vectorBuffer(vector2);
|
|
|
|
|
vectorBuffer(vector3);
|
|
|
|
|
vectorBuffer(vector4);
|
|
|
|
|
vectorBuffer(vector2d);
|
|
|
|
|
vectorBuffer(vector3d);
|
|
|
|
|
vectorBuffer(vector4d);
|
|
|
|
|
vectorBuffer(color3_);
|
|
|
|
|
vectorBuffer(color4_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|