File: OpenGLRenderer.hpp

package info (click to toggle)
yade 2026.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,448 kB
  • sloc: cpp: 97,645; python: 52,173; sh: 677; makefile: 162
file content (145 lines) | stat: -rw-r--r-- 6,711 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// © 2004 Olivier Galizzi <olivier.galizzi@imag.fr>
// © 2008 Václav Šmilauer <eudoxos@arcig.cz>
#pragma once

#include <lib/multimethods/DynLibDispatcher.hpp>
#include <core/Body.hpp>
#include <core/Dispatcher.hpp>
#include <pkg/common/GLDrawFunctors.hpp>

namespace yade { // Cannot have #include directive inside.

struct GlExtraDrawer : public Serializable {
	Scene*       scene;
	virtual void render();
	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS(GlExtraDrawer,Serializable,"Performing arbitrary OpenGL drawing commands; called from :yref:`OpenGLRenderer` (see :yref:`OpenGLRenderer.extraDrawers`) once regular rendering routines will have finished.\n\nThis class itself does not render anything, derived classes should override the *render* method.",
		((bool,dead,false,,"Deactivate the object (on error/exception)."))
	);
	// clang-format on
};
REGISTER_SERIALIZABLE(GlExtraDrawer);

class OpenGLRenderer : public Serializable {
public:
	static const int numClipPlanes = 3;

	bool             pointClipped(const Vector3r& p);
	vector<Vector3r> clipPlaneNormals;
	void             setBodiesDispInfo();
	static bool      initDone;
	Vector3r         viewDirection; // updated from GLViewer regularly
	GLViewInfo       viewInfo;      // update from GLView regularly
	Vector3r         highlightEmission0;
	Vector3r         highlightEmission1;

	// normalized saw signal with given periodicity, with values ∈ 〈0,1〉 */
	Real normSaw(Real t, Real period)
	{
		Real xi = (t - period * ((int)(t / period))) / period; /* normalized value, (0-1〉 */
		return (xi < .5 ? 2 * xi : 2 - 2 * xi);
	}
	Real normSquare(Real t, Real period)
	{
		Real xi = (t - period * ((int)(t / period))) / period; /* normalized value, (0-1〉 */
		return (xi < .5 ? 0 : 1);
	}

	void drawPeriodicCell();

	void setBodiesRefSe3();

	struct BodyDisp {
		Vector3r    pos;
		Quaternionr ori;
		bool        isDisplayed;
		bool        hidden;
	};
	//! display data for individual bodies
	vector<BodyDisp> bodyDisp;
	void             hide(Body::id_t id2)
	{
		if ((unsigned int)id2 < bodyDisp.size()) bodyDisp[id2].hidden = true;
	}
	void show(Body::id_t id2)
	{
		if ((unsigned int)id2 < bodyDisp.size()) bodyDisp[id2].hidden = false;
	}

	virtual ~OpenGLRenderer();

private:
	void resetSpecularEmission();

	GlBoundDispatcher boundDispatcher;
	GlIGeomDispatcher geomDispatcher;
	GlIPhysDispatcher physDispatcher;
	GlShapeDispatcher shapeDispatcher;
	// GlStateDispatcher stateDispatcher;


	vector<string>
	        // stateFunctorNames,
	        boundFunctorNames, shapeFunctorNames, geomFunctorNames, physFunctorNames;

	DECLARE_LOGGER;

public:
	// updated after every call to render
	shared_ptr<Scene> scene;

	void init();
	void initgl();
	void render(const shared_ptr<Scene>& scene, Body::id_t selection = Body::id_t(-1));
	void pyRender() { render(Omega::instance().getScene()); }

	void renderDOF_ID();
	void renderIPhys();
	void renderIGeom();
	void renderBound();
	// called also to render selectable entitites;
	void                                                 renderShape();
	void                                                 renderAllInteractionsWire();
	template <class FunctorType, class DispatcherT> void setupDispatcher(const vector<string>& names, DispatcherT& dispatcher);
	enum class BlinkHighlight { NEVER, NORMAL, WEAK };

	// clang-format off
	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(OpenGLRenderer,Serializable,"Class responsible for rendering scene on OpenGL devices.",
		((Vector3r,dispScale,((void)"disable scaling",Vector3r::Ones()),,"Artificially enlarge (scale) dispalcements from bodies' :yref:`reference positions<State.refPos>` by this relative amount, so that they become better visible (independently in 3 dimensions). Disbled if (1,1,1)."))
		((Real,rotScale,((void)"disable scaling",1.),,"Artificially enlarge (scale) rotations of bodies relative to their :yref:`reference orientation<State.refOri>`, so the they are better visible."))
		((Vector3r,lightPos,Vector3r(75,130,0),,"Position of OpenGL light source in the scene."))
		((Vector3r,light2Pos,Vector3r(-130,75,30),,"Position of secondary OpenGL light source in the scene."))
		((Vector3r,lightColor,Vector3r(0.6,0.6,0.6),,"Per-color intensity of primary light (RGB)."))
		((Vector3r,light2Color,Vector3r(0.5,0.5,0.1),,"Per-color intensity of secondary light (RGB)."))
		((Vector3r,cellColor,Vector3r(1,1,0),,"Color of the periodic cell (RGB)."))
		((Vector3r,bgColor,Vector3r(.2,.2,.2),,"Color of the background canvas (RGB)"))
		((BlinkHighlight,blinkHighlight,BlinkHighlight::NORMAL,,"Adjust blinking of the body selected in the 'Simulation Inspection' window."))
		((bool,wire,false,,"Render all bodies with wire only (faster)"))
		((bool,light1,true,,"Turn light 1 on."))
		((bool,light2,true,,"Turn light 2 on."))
		((bool,dof,false,,"Show which degrees of freedom are blocked for each body"))
		((bool,id,false,,"Show body id's"))
		((bool,bound,false,,"Render body :yref:`Bound`"))
		((bool,shape,true,,"Render body :yref:`Shape`"))
		((bool,intrWire,false,,"If rendering interactions, use only wires to represent them."))
		((bool,intrGeom,false,,"Render :yref:`Interaction::geom` objects."))
		((bool,intrPhys,false,,"Render :yref:`Interaction::phys` objects"))
		((bool,ghosts,true,,"Render objects crossing periodic cell edges by cloning them in multiple places (periodic simulations only)."))
		((int,mask,((void)"draw everything",~0),,"Bitmask for showing only bodies where ((mask & :yref:`Body::mask`)!=0)"))
		((Body::id_t,selId,Body::ID_NONE,,"Id of particle that was selected by the user."))
		((vector<Se3r>,clipPlaneSe3,vector<Se3r>(numClipPlanes,Se3r(Vector3r::Zero(),Quaternionr::Identity())),,"Position and orientation of clipping planes"))
		((vector<bool>,clipPlaneActive,vector<bool>(numClipPlanes,false),,"Activate/deactivate respective clipping planes"))
		((vector<shared_ptr<GlExtraDrawer> >,extraDrawers,,,"Additional rendering components (:yref:`GlExtraDrawer`)."))
		((bool,intrAllWire,false,,"Draw wire for all interactions, blue for potential and green for real ones (mostly for debugging)")),
		/*ctor*/,
		/*py*/
		.def("setRefSe3",&OpenGLRenderer::setBodiesRefSe3,"Make current positions and orientation reference for scaleDisplacements and scaleRotations.")
		.def("render",&OpenGLRenderer::pyRender,"Render the scene in the current OpenGL context.")
		.def("hideBody",&OpenGLRenderer::hide,(boost::python::arg("id")),"Hide body from id (see :yref:`OpenGLRenderer::showBody`)")
		.def("showBody",&OpenGLRenderer::show,(boost::python::arg("id")),"Make body visible (see :yref:`OpenGLRenderer::hideBody`)")
	);
	// clang-format on
};
REGISTER_SERIALIZABLE(OpenGLRenderer);

} // namespace yade