mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 08:15:18 -04:00
collide: Expose CollisionPolygon's setup_points and verify_points to Python
Closes #1035
This commit is contained in:
parent
3d5f0b7fe1
commit
ac6a1a7874
@ -3829,6 +3829,7 @@ OPTS=['DIR:panda/src/collide']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/collide', ["*.h", "*_composite*.cxx"])
|
||||
TargetAdd('libp3collide.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3collide.in', opts=['IMOD:panda3d.core', 'ILIB:libp3collide', 'SRCDIR:panda/src/collide'])
|
||||
PyTargetAdd('p3collide_ext_composite.obj', opts=OPTS, input='p3collide_ext_composite.cxx')
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/parametrics/
|
||||
@ -4073,6 +4074,7 @@ PyTargetAdd('core.pyd', input='p3event_pythonTask.obj')
|
||||
PyTargetAdd('core.pyd', input='p3gobj_ext_composite.obj')
|
||||
PyTargetAdd('core.pyd', input='p3pgraph_ext_composite.obj')
|
||||
PyTargetAdd('core.pyd', input='p3display_ext_composite.obj')
|
||||
PyTargetAdd('core.pyd', input='p3collide_ext_composite.obj')
|
||||
|
||||
PyTargetAdd('core.pyd', input='core_module.obj')
|
||||
if not GetLinkAllStatic() and GetTarget() != 'emscripten':
|
||||
|
@ -65,11 +65,16 @@ set(P3COLLIDE_SOURCES
|
||||
config_collide.cxx
|
||||
)
|
||||
|
||||
set(P3COLLIDE_IGATEEXT
|
||||
collisionPolygon_ext.cxx
|
||||
collisionPolygon_ext.h
|
||||
)
|
||||
|
||||
composite_sources(p3collide P3COLLIDE_SOURCES)
|
||||
add_component_library(p3collide SYMBOL BUILDING_PANDA_COLLIDE
|
||||
${P3COLLIDE_HEADERS} ${P3COLLIDE_SOURCES})
|
||||
target_link_libraries(p3collide p3tform)
|
||||
target_interrogate(p3collide ALL)
|
||||
target_interrogate(p3collide ALL EXTENSIONS ${P3COLLIDE_IGATEEXT})
|
||||
|
||||
if(NOT BUILD_METALIBS)
|
||||
install(TARGETS p3collide
|
||||
|
@ -59,6 +59,9 @@ PUBLISHED:
|
||||
bool is_valid() const;
|
||||
bool is_concave() const;
|
||||
|
||||
EXTENSION(static bool verify_points(PyObject *points));
|
||||
EXTENSION(void setup_points(PyObject *points));
|
||||
|
||||
PUBLISHED:
|
||||
MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
|
||||
MAKE_PROPERTY(valid, is_valid);
|
||||
@ -71,6 +74,8 @@ public:
|
||||
const CullTraverserData &data,
|
||||
bool bounds_only) const;
|
||||
|
||||
void setup_points(const LPoint3 *begin, const LPoint3 *end);
|
||||
|
||||
virtual PStatCollector &get_volume_pcollector();
|
||||
virtual PStatCollector &get_test_pcollector();
|
||||
|
||||
@ -128,7 +133,6 @@ private:
|
||||
PN_stdfloat dist_to_polygon(const LPoint2 &p, LPoint2 &edge_p, const Points &points) const;
|
||||
void project(const LVector3 &axis, PN_stdfloat ¢er, PN_stdfloat &extent) const;
|
||||
|
||||
void setup_points(const LPoint3 *begin, const LPoint3 *end);
|
||||
INLINE LPoint2 to_2d(const LVecBase3 &point3d) const;
|
||||
INLINE void calc_to_3d_mat(LMatrix4 &to_3d_mat) const;
|
||||
INLINE void rederive_to_3d_mat(LMatrix4 &to_3d_mat) const;
|
||||
|
86
panda/src/collide/collisionPolygon_ext.cxx
Normal file
86
panda/src/collide/collisionPolygon_ext.cxx
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file collisionPolygon_ext.cxx
|
||||
* @author Derzsi Daniel
|
||||
* @date 2020-10-13
|
||||
*/
|
||||
|
||||
#include "collisionPolygon_ext.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#include "collisionPolygon.h"
|
||||
|
||||
#ifdef STDFLOAT_DOUBLE
|
||||
extern struct Dtool_PyTypedObject Dtool_LPoint3d;
|
||||
#else
|
||||
extern struct Dtool_PyTypedObject Dtool_LPoint3f;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Verifies that the indicated Python list of points will define a
|
||||
* CollisionPolygon.
|
||||
*/
|
||||
bool Extension<CollisionPolygon>::
|
||||
verify_points(PyObject *points) {
|
||||
const pvector<LPoint3> vec = convert_points(points);
|
||||
const LPoint3 *verts_begin = &vec[0];
|
||||
const LPoint3 *verts_end = verts_begin + vec.size();
|
||||
|
||||
return CollisionPolygon::verify_points(verts_begin, verts_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this CollisionPolygon with the given Python list of
|
||||
* points.
|
||||
*/
|
||||
void Extension<CollisionPolygon>::
|
||||
setup_points(PyObject *points) {
|
||||
const pvector<LPoint3> vec = convert_points(points);
|
||||
const LPoint3 *verts_begin = &vec[0];
|
||||
const LPoint3 *verts_end = verts_begin + vec.size();
|
||||
|
||||
_this->setup_points(verts_begin, verts_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Python sequence to a list of LPoint3 objects.
|
||||
*/
|
||||
pvector<LPoint3> Extension<CollisionPolygon>::
|
||||
convert_points(PyObject *points) {
|
||||
pvector<LPoint3> vec;
|
||||
PyObject *seq = PySequence_Fast(points, "function expects a sequence");
|
||||
|
||||
if (!seq) {
|
||||
return vec;
|
||||
}
|
||||
|
||||
PyObject **items = PySequence_Fast_ITEMS(seq);
|
||||
Py_ssize_t len = PySequence_Fast_GET_SIZE(seq);
|
||||
void *ptr;
|
||||
|
||||
vec.reserve(len);
|
||||
|
||||
for (Py_ssize_t i = 0; i < len; ++i) {
|
||||
#ifdef STDFLOAT_DOUBLE
|
||||
if (ptr = DtoolInstance_UPCAST(items[i], Dtool_LPoint3d)) {
|
||||
#else
|
||||
if (ptr = DtoolInstance_UPCAST(items[i], Dtool_LPoint3f)) {
|
||||
#endif
|
||||
vec.push_back(*(LPoint3 *)ptr);
|
||||
} else {
|
||||
collide_cat.warning() << "Argument must be of LPoint3 type.\n";
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(seq);
|
||||
return vec;
|
||||
}
|
||||
|
||||
#endif
|
43
panda/src/collide/collisionPolygon_ext.h
Normal file
43
panda/src/collide/collisionPolygon_ext.h
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file collisionPolygon_ext.h
|
||||
* @author Derzsi Daniel
|
||||
* @date 2020-10-13
|
||||
*/
|
||||
|
||||
#ifndef COLLISIONPOLYGON_EXT_H
|
||||
#define COLLISIONPOLYGON_EXT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#include "extension.h"
|
||||
#include "collisionPolygon.h"
|
||||
#include "py_panda.h"
|
||||
|
||||
/**
|
||||
* This class defines the extension methods for CollisionPolygon, which are called
|
||||
* instead of any C++ methods with the same prototype.
|
||||
*
|
||||
* @since 1.11.0
|
||||
*/
|
||||
template<>
|
||||
class Extension<CollisionPolygon> : public ExtensionBase<CollisionPolygon> {
|
||||
public:
|
||||
static bool verify_points(PyObject *points);
|
||||
void setup_points(PyObject *points);
|
||||
|
||||
private:
|
||||
static pvector<LPoint3> convert_points(PyObject *points);
|
||||
};
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#endif
|
1
panda/src/collide/p3collide_ext_composite.cxx
Normal file
1
panda/src/collide/p3collide_ext_composite.cxx
Normal file
@ -0,0 +1 @@
|
||||
#include "collisionPolygon_ext.cxx"
|
45
tests/collide/test_collision_polygon.py
Normal file
45
tests/collide/test_collision_polygon.py
Normal file
@ -0,0 +1,45 @@
|
||||
from panda3d import core
|
||||
|
||||
|
||||
def test_collision_polygon_verify_not_enough_points():
|
||||
# Less than 3 points cannot create a polygon
|
||||
assert not core.CollisionPolygon.verify_points([])
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0)])
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0), core.LPoint3(0, 0, 1)])
|
||||
|
||||
|
||||
def test_collision_polygon_verify_repeating_points():
|
||||
# Repeating points cannot create a polygon
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0), core.LPoint3(1, 0, 0), core.LPoint3(0, 0, 1)])
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(3, 6, 1), core.LPoint3(1, 3, 5), core.LPoint3(9, 1, 2), core.LPoint3(1, 3, 5)])
|
||||
|
||||
|
||||
def test_collision_polygon_verify_colinear_points():
|
||||
# Colinear points cannot create a polygon
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 2, 3), core.LPoint3(2, 3, 4), core.LPoint3(3, 4, 5)])
|
||||
assert not core.CollisionPolygon.verify_points([core.LPoint3(2, 1, 1), core.LPoint3(3, 2, 1), core.LPoint3(4, 3, 1)])
|
||||
|
||||
|
||||
def test_collision_polygon_verify_points():
|
||||
# Those should be regular, colinear points
|
||||
assert core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0), core.LPoint3(0, 1, 0), core.LPoint3(0, 0, 1)])
|
||||
assert core.CollisionPolygon.verify_points([core.LPoint3(10, 2, 8), core.LPoint3(7, 1, 3), core.LPoint3(5, 9, 6)])
|
||||
assert core.CollisionPolygon.verify_points([core.LPoint3(3, -8, -7), core.LPoint3(9, 10, 8), core.LPoint3(7, 0, 10), core.LPoint3(-6, -2, 3)])
|
||||
assert core.CollisionPolygon.verify_points([core.LPoint3(-1, -3, -5), core.LPoint3(10, 3, -10), core.LPoint3(-10, 10, -4), core.LPoint3(0, 1, -4), core.LPoint3(-9, -2, 0)])
|
||||
|
||||
|
||||
def test_collision_polygon_setup_points():
|
||||
# Create empty collision polygon
|
||||
polygon = core.CollisionPolygon(core.LVecBase3(0, 0, 0), core.LVecBase3(0, 0, 0), core.LVecBase3(0, 0, 0))
|
||||
assert not polygon.is_valid()
|
||||
|
||||
# Test our setup method against a few test cases
|
||||
for points in [
|
||||
[core.LPoint3(-1, -3, -5), core.LPoint3(10, 3, -10), core.LPoint3(-10, 10, -4), core.LPoint3(0, 1, -4), core.LPoint3(-9, -2, 0)],
|
||||
[core.LPoint3(3, -8, -7), core.LPoint3(9, 10, 8), core.LPoint3(7, 0, 10), core.LPoint3(-6, -2, 3)],
|
||||
[core.LPoint3(1, 0, 0), core.LPoint3(0, 1, 0), core.LPoint3(0, 0, 1)],
|
||||
[core.LPoint3(10, 2, 8), core.LPoint3(7, 1, 3), core.LPoint3(5, 9, 6)]
|
||||
]:
|
||||
polygon.setup_points(points)
|
||||
assert polygon.is_valid()
|
||||
assert polygon.get_num_points() == len(points)
|
Loading…
x
Reference in New Issue
Block a user