Skip to content

Commit af16b37

Browse files
author
Felix Igelbrink
committed
python interfacing works. Implementted simple EPT-Format reader as a showcase
1 parent 75acdc1 commit af16b37

11 files changed

+321
-130
lines changed

src/gil.h

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// Taken from the pybind11 project: https://github.com/pybind/pybind11/blob/14976c853b8422dc41ce7874742cab122684c97e/include/pybind11/gil.h
3+
//
4+
//Copyright (c) 2016 Wenzel Jakob <[email protected]>, All rights reserved.
5+
//
6+
//Redistribution and use in source and binary forms, with or without
7+
// modification, are permitted provided that the following conditions are met:
8+
//
9+
//1. Redistributions of source code must retain the above copyright notice, this
10+
//list of conditions and the following disclaimer.
11+
//
12+
//2. Redistributions in binary form must reproduce the above copyright notice,
13+
//this list of conditions and the following disclaimer in the documentation
14+
//and/or other materials provided with the distribution.
15+
//
16+
//3. Neither the name of the copyright holder nor the names of its contributors
17+
// may be used to endorse or promote products derived from this software
18+
// without specific prior written permission.
19+
//
20+
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21+
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22+
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
//OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
//
31+
//Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
32+
//external contributions to this project including patches, pull requests, etc.
33+
34+
#pragma once
35+
#include <Python.h>
36+
37+
class gil_scoped_release {
38+
public:
39+
explicit gil_scoped_release() {
40+
// `get_internals()` must be called here unconditionally in order to initialize
41+
// `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an
42+
// initialization race could occur as multiple threads try `gil_scoped_acquire`.
43+
tstate = PyEval_SaveThread();
44+
}
45+
//
46+
// gil_scoped_release(gil_scoped_release&& other) noexcept
47+
// : tstate(other.tstate), active(other.active) {
48+
// other.tstate = nullptr;
49+
// other.active = false;
50+
// }
51+
//
52+
// gil_scoped_release& operator=(gil_scoped_release&& other) noexcept {
53+
// tstate = other.tstate;
54+
// other.tstate = nullptr;
55+
// active = other.active;
56+
// other.active = false;
57+
// return *this;
58+
// }
59+
60+
/// This method will disable the PyThreadState_DeleteCurrent call and the
61+
/// GIL won't be acquired. This method should be used if the interpreter
62+
/// could be shutting down when this is called, as thread deletion is not
63+
/// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
64+
/// protect subsequent code.
65+
void disarm() {
66+
active = false;
67+
}
68+
69+
~gil_scoped_release() {
70+
if (!tstate)
71+
return;
72+
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
73+
if (active)
74+
PyEval_RestoreThread(tstate);
75+
}
76+
private:
77+
PyThreadState *tstate;
78+
bool active = true;
79+
};

src/vtkPythonLoader.cxx

+5-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "vtkPythonLoader.h"
66
#include "vtkTileHierarchyNode.h"
77
#include "vtkAttributedTileHierarchyNode.h"
8+
#include "gil.h"
89
#include <vtkMapper.h>
910
#include <vtkObjectFactory.h>
1011
#include <vtkCommand.h>
@@ -29,17 +30,10 @@ void vtkPythonLoader::FetchNode(vtkTileHierarchyNodePtr node) {
2930
Superclass::InvokeEvent(FetchNodeEvent, node);
3031
}
3132

32-
//void vtkPythonLoader::DummyFetch() {
33-
// vtkBoundingBox bounds(0, 1, 0, 1, 0,1);
34-
// auto dummy_node = vtkAttributedTileHierarchyNodePtr::New();
35-
// dummy_node->SetBoundingBox(bounds);
36-
// dummy_node->SetSize(10);
37-
// dummy_node->SetAttribute("name", "my_node_name");
38-
// gil_scoped_release release; // release the Python GIL here so the thread can run!
39-
// std::thread foo(&vtkPythonLoader::FetchNode, this, dummy_node);
40-
// foo.join();
41-
//}
42-
4333
void vtkPythonLoader::PrintSelf(ostream &os, vtkIndent indent) {
4434
Superclass::PrintSelf(os, indent);
35+
}
36+
37+
std::unique_ptr<vtkTileHierarchyLoaderRenderState> vtkPythonLoader::PreRender() {
38+
return std::make_unique<vtkTileHierarchyLoaderRenderStatePython>();
4539
}

src/vtkPythonLoader.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <memory>
1111
#include "vtkTileHierarchyLoader.h"
1212
#include "vtkTileHierarchyModule.h" // For export macro
13+
#include "gil.h"
1314

1415
class vtkCommand;
1516
class vtkMapper;
@@ -18,6 +19,17 @@ class vtkBoundingBox;
1819
class vtkTileHierarchyNode;
1920
using vtkTileHierarchyNodePtr = vtkSmartPointer<vtkTileHierarchyNode>;
2021

22+
23+
class vtkTileHierarchyLoaderRenderStatePython: public vtkTileHierarchyLoaderRenderState {
24+
public:
25+
vtkTileHierarchyLoaderRenderStatePython()
26+
: release() { };
27+
~vtkTileHierarchyLoaderRenderStatePython() override {
28+
};
29+
private:
30+
gil_scoped_release release;
31+
};
32+
2133
class VTKTILEHIERARCHY_EXPORT vtkPythonLoader: public vtkTileHierarchyLoader {
2234
public:
2335
static vtkPythonLoader* New();
@@ -27,7 +39,8 @@ class VTKTILEHIERARCHY_EXPORT vtkPythonLoader: public vtkTileHierarchyLoader {
2739
void Initialize() override;
2840
void FetchNode(vtkTileHierarchyNodePtr node) override;
2941

30-
//void DummyFetch();
42+
43+
VTK_WRAPEXCLUDE std::unique_ptr<vtkTileHierarchyLoaderRenderState> PreRender() override;
3144

3245
vtkGetMacro(InitializeEvent, unsigned long);
3346
vtkGetMacro(FetchNodeEvent, unsigned long);

src/vtkTileHierarchyLoader.cxx

+1-21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <vtkMapper.h>
1111
#include <vtkDataSetMapper.h>
1212

13+
1314
std::size_t std::hash<vtkTileHierarchyNodePtr>::operator()(const vtkTileHierarchyNodePtr &s) const noexcept {
1415
return std::hash<vtkTileHierarchyNode *>{}(s.GetPointer());
1516
}
@@ -21,28 +22,13 @@ size_t vtkTileHierarchyLoader::TileTreeNodeSize::operator()(const vtkTileHierarc
2122

2223
vtkTileHierarchyLoader::vtkTileHierarchyLoader()
2324
: RootNode(nullptr), Cache(15000000) {
24-
//MapperTemplate->SetColorModeToMapScalars();
25-
//MapperTemplate->SetScalarModeToUsePointData();
26-
//MapperTemplate->SetStatic(true);
2725

2826
}
2927

30-
//void vtkTileHierarchyLoader::SetMapperTemplate(vtkMapper *mapper) {
31-
// MapperTemplate.TakeReference(mapper);
32-
//}
33-
//
34-
//vtkMapper * vtkTileHierarchyLoader::GetMapperTemplate() {
35-
// return MapperTemplate.Get();
36-
//}
37-
3828
void vtkTileHierarchyLoader::PrintSelf(ostream &os, vtkIndent indent) {
3929
Superclass::PrintSelf(os, indent);
4030
}
4131

42-
//bool vtkTileHierarchyLoader::IsCached(const vtkTileHierarchyNodePtr &node) const {
43-
// return Cache.exist(node);
44-
//}
45-
4632
vtkTileHierarchyNodePtr vtkTileHierarchyLoader::GetRootNode() {
4733
if(!RootNode) Initialize();
4834
return RootNode;
@@ -54,7 +40,6 @@ void vtkTileHierarchyLoader::SetRootNode(vtkTileHierarchyNode* root_node) {
5440
}
5541

5642
vtkSmartPointer<vtkMapper> vtkTileHierarchyLoader::MakeMapper() const {
57-
//auto mapper = vtkSmartPointer<vtkMapper>::NewInstance(MapperTemplate);
5843
auto mapper = vtkSmartPointer<vtkDataSetMapper>::New();
5944
assert(mapper->GetReferenceCount() == 1);
6045
mapper->SetStatic(true);
@@ -68,11 +53,8 @@ bool vtkTileHierarchyLoader::TryGetNodeFromCache(vtkTileHierarchyNodePtr &node)
6853
std::scoped_lock<std::mutex> node_lock{node->GetMutex()};
6954
node->Mapper = vtkSmartPointer(std::move(val.first));
7055
node->Size = val.second;
71-
//Cache.erase(node); // Remove the node from cache as long as it is used by the mapper
72-
//node_lock.unlock();
7356
return true;
7457
}
75-
//if(node_lock) node_lock.unlock();
7658
return false;
7759
}
7860

@@ -89,8 +71,6 @@ void vtkTileHierarchyLoader::LoadNode(vtkTileHierarchyNodePtr &node, bool recurs
8971
if(!node->IsLoaded()) {
9072
FetchNode(node);
9173
}
92-
//if(!TryGetNodeFromCache(node) && !node->IsLoaded()) { // avoid loading nodes that are already in use or cached
93-
//}
9474
// recursively load all nodes below as well
9575
if (recursive)
9676
{

src/vtkTileHierarchyLoader.h

+13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <vtkSmartPointer.h>
1111
#include <vtkObject.h>
1212
#include <memory>
13+
#include <any>
1314
#include "vtkTileHierarchyModule.h" // For export macro
1415

1516

@@ -26,6 +27,11 @@ class vtkMapper;
2627

2728
class vtkTileHierarchyLoaderThread;
2829

30+
struct vtkTileHierarchyLoaderRenderState {
31+
vtkTileHierarchyLoaderRenderState() = default;
32+
virtual ~vtkTileHierarchyLoaderRenderState() = default;
33+
};
34+
2935
class VTKTILEHIERARCHY_EXPORT vtkTileHierarchyLoader: public vtkObject {
3036
public:
3137
vtkTypeMacro(vtkTileHierarchyLoader, vtkObject);
@@ -43,6 +49,13 @@ class VTKTILEHIERARCHY_EXPORT vtkTileHierarchyLoader: public vtkObject {
4349
UnloadNode(node, false);
4450
}
4551

52+
VTK_WRAPEXCLUDE virtual std::unique_ptr<vtkTileHierarchyLoaderRenderState> PreRender() {
53+
return std::make_unique<vtkTileHierarchyLoaderRenderState>();
54+
};
55+
56+
VTK_WRAPEXCLUDE virtual void PostRender(std::unique_ptr<vtkTileHierarchyLoaderRenderState> state) {
57+
};
58+
4659
VTK_WRAPEXCLUDE void UnloadNode(vtkTileHierarchyNodePtr& node, bool recursive);
4760

4861
VTK_WRAPEXCLUDE virtual void FetchNode(vtkTileHierarchyNodePtr node) = 0;

src/vtkTileHierarchyMapper.cxx

+2-85
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@
1616
#include <vtkExecutive.h>
1717
#include <vtkRenderWindowInteractor.h>
1818

19-
20-
//bool is_different(const vtkMatrix4x4* first, const vtkMatrix4x4* second) {
21-
// for (int i = 0; i < 4; ++i)
22-
// for (int j = 0; j < 4; ++j)
23-
// if (first->GetElement(i, j) != second->GetElement(i, j)) return true;
24-
// return false;
25-
//}
26-
2719
enum FrustumCull
2820
{
2921
INSIDE_FRUSTUM,
@@ -72,82 +64,6 @@ int intersect(vtkCamera* camera, const vtkBoundingBox& bbox, double aspect_ratio
7264
return result;
7365
}
7466

75-
//class CheckVisibilityCallback: public vtkCallbackCommand {
76-
//public:
77-
// static CheckVisibilityCallback* New();
78-
// vtkTypeMacro(CheckVisibilityCallback, vtkCallbackCommand);
79-
//
80-
// // Here we Create a vtkCallbackCommand and reimplement it.
81-
// void Execute(vtkObject* caller, unsigned long evId, void*) override
82-
// {
83-
// std::cout << "Camera moved" << std::endl;
84-
// // Note the use of reinterpret_cast to cast the caller to the expected type.
85-
// auto camera = Mapper->Renderer->GetActiveCamera();//reinterpret_cast<vtkCamera*>(caller);
86-
// vtkVector3d camera_position;
87-
// camera->GetPosition(camera_position.GetData());
88-
// vtkQuaterniond camera_orientation(camera->GetOrientationWXYZ());
89-
// vtkSmartPointer<vtkMatrix4x4> projection_matrix;
90-
// projection_matrix.TakeReference(camera->GetProjectionTransformMatrix(Mapper->Renderer));
91-
//
92-
// vtkVector3d camera_position_difference;
93-
// vtkMath::Subtract(camera_position.GetData(), LastPosition.GetData(), camera_position_difference.GetData());
94-
// bool projection_different = true;
95-
// if(LastProjection) {
96-
// projection_different = is_different(projection_matrix, LastProjection);
97-
// }
98-
// if (!projection_different
99-
// && camera_position_difference.Norm() < 0.01f
100-
// && (camera_orientation - LastOrientation).Norm() < 0.01f)
101-
// return;
102-
// LastPosition = camera_position;
103-
// LastOrientation = camera_orientation;
104-
// LastProjection = projection_matrix;
105-
// if(Mapper->Renderer)
106-
// //std::cout << "Re-Rendering due to moved camera" << std::endl;
107-
// Mapper->Renderer->GetRenderWindow()->Render(); // force a render
108-
// }
109-
// CheckVisibilityCallback(): Mapper(nullptr)
110-
// {
111-
// }
112-
//
113-
// // Set pointers to any clientData or callData here.
114-
// vtkTileHierarchyMapper* Mapper;
115-
// vtkVector3d LastPosition;
116-
// vtkQuaterniond LastOrientation;
117-
// vtkSmartPointer<vtkMatrix4x4> LastProjection;
118-
//};
119-
//
120-
//class ReRenderCallback: public vtkCallbackCommand {
121-
//public:
122-
// static ReRenderCallback* New();
123-
// vtkTypeMacro(ReRenderCallback, vtkCallbackCommand);
124-
//
125-
// // Here we Create a vtkCallbackCommand and reimplement it.
126-
// void Execute(vtkObject* caller, unsigned long evId, void*) override
127-
// {
128-
// // Note the use of reinterpret_cast to cast the caller to the expected type.
129-
// if (vtkCommand::TimerEvent == evId) {
130-
// if(Mapper->ForceUpdate && Mapper->Renderer) {
131-
// std::cout << "Re-rendering " << count++ << std::endl;
132-
// Mapper->Renderer->GetRenderWindow()->Render(); // force a render
133-
// }
134-
// }
135-
// }
136-
// ReRenderCallback(): Mapper(nullptr)
137-
// {
138-
// }
139-
//
140-
// // Set pointers to any clientData or callData here.
141-
// vtkTileHierarchyMapper* Mapper;
142-
// size_t count = 0;
143-
//};
144-
//
145-
//
146-
//vtkStandardNewMacro(CheckVisibilityCallback);
147-
//vtkStandardNewMacro(ReRenderCallback);
148-
149-
150-
15167
vtkStandardNewMacro(vtkTileHierarchyMapper);
15268

15369
vtkTileHierarchyMapper::vtkTileHierarchyMapper()
@@ -205,7 +121,7 @@ void vtkTileHierarchyMapper::OnNodeLoaded() {
205121
}
206122

207123
void vtkTileHierarchyMapper::Render(vtkRenderer *ren, vtkActor *a) {
208-
//std::cout << "Rendering" << std::endl;
124+
auto loader_state = Loader->PreRender();
209125
ForceUpdate = false;
210126

211127
if(ren->GetRenderWindow()->GetActualSize()[1] < 10) {
@@ -250,6 +166,7 @@ void vtkTileHierarchyMapper::Render(vtkRenderer *ren, vtkActor *a) {
250166

251167
}
252168
}
169+
Loader->PostRender(std::move(loader_state));
253170
}
254171

255172

src/vtkTileHierarchyNode.cxx

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void vtkTileHierarchyNode::PrintSelf(ostream &os, vtkIndent indent) {
2020
}
2121

2222
void vtkTileHierarchyNode::Render(vtkRenderer *ren, vtkActor *a) {
23-
std::lock_guard<std::mutex> lock{Mutex};
23+
//std::lock_guard<std::mutex> lock{Mutex};
2424
if(!Mapper) return;
2525

2626
Mapper->Render(ren, a);
@@ -50,7 +50,7 @@ void vtkTileHierarchyNode::SetChild(vtkIdType idx, vtkTileHierarchyNode* child)
5050

5151
void vtkTileHierarchyNode::ResetNode() {
5252
Mapper = nullptr;
53-
Size = 0;
53+
//Size = 0;
5454
}
5555

5656
void vtkTileHierarchyNode::SetMapper(vtkMapper* mapper) {

vtk_tile_hierarchy/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .vtkTileHierarchy import vtkPotreeLoader, vtkTileHierarchyLoader, vtkTileHierarchyNode, vtkAttributedTileHierarchyNode, vtkPointHierarchyNode, vtkTileHierarchyMapper
22
from .python_hierarchy_loader import vtkPythonHierarchyLoader
3-
from .python_hierarchy_node import vtkTileHierarchyNodePython
3+
from .python_hierarchy_node import vtkTileHierarchyNodePython
4+
from .ept_loader import vtkEptLoader

0 commit comments

Comments
 (0)