diff --git a/README.rst b/README.rst index 29a3dd3d..089f9b97 100644 --- a/README.rst +++ b/README.rst @@ -2,11 +2,11 @@ Exudyn ====== -+ Exudyn version = 1.2.134.dev1 (Corea) -+ build date and time=2022-06-17 01:34 ++ Exudyn version = 1.3.0 (Davis) ++ build date and time=2022-06-22 08:18 + **University of Innsbruck**, Austria, Department of Mechatronics -Exudyn now includes a redundant coordinate (constraint) as well as a minimum coordinate formulation (KinematicTree); machine learning and artificial intelligence interface (openAI gym); improved explicit and implicit solvers; sparse matrix support and multi-threading; basic hydraulic actuator; creation of beams along curves; extended robotics modules; contact module; **PlotSensor** for simple post processing, ... See theDoc.pdf chapter **Issues and Bugs** for changes! +Exudyn 1.3 is out! It includes a redundant coordinate (constraint) as well as a minimum coordinate formulation (KinematicTree); machine learning and artificial intelligence interface (openAI gym); improved explicit and implicit solvers; sparse matrix support and multi-threading; basic hydraulic actuator; creation of beams along curves; extended robotics modules; contact module; **PlotSensor** for simple post processing, and some improved 3D visualization, ... See theDoc.pdf chapter **Issues and Bugs** for changes! If you like using Exudyn, please add a *star* on github, and send an email to ``reply.exudyn@gmail.com`` such that we can add you to our newsletter. Let us know, which features you are using or which **features you are missing** and follow us on `Twitter @RExudyn `_ ! diff --git a/docs/howTo/ubuntuPythonSetup.txt b/docs/howTo/ubuntuPythonSetup.txt index e8f134d1..a04c2686 100644 --- a/docs/howTo/ubuntuPythonSetup.txt +++ b/docs/howTo/ubuntuPythonSetup.txt @@ -52,6 +52,18 @@ os.environ["CXX"] = "gcc-8" #or follow these hints to switch between different gcc versions (UBUNTU20.04?): https://linuxconfig.org/how-to-switch-between-multiple-gcc-and-g-compiler-versions-on-ubuntu-20-04-lts-focal-fossa + +=============================================== +#OPENGL on linux (for special examples, not using glfw): +sudo apt-get install mesa-utils +sudo apt-get install freeglut3-dev +#find GL include files: +dpkg -L freeglut3-dev + +#see https://askubuntu.com/questions/96087/how-to-install-opengl-glut-libraries +=============================================== + + #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG #DEBUG on linux: diff --git a/docs/theDoc/buildDate.tex b/docs/theDoc/buildDate.tex index 483e2c3a..b3d2eb76 100644 --- a/docs/theDoc/buildDate.tex +++ b/docs/theDoc/buildDate.tex @@ -1 +1 @@ -build date and time=2022-06-17 01:34 \ No newline at end of file +build date and time=2022-06-22 08:18 \ No newline at end of file diff --git a/docs/theDoc/gettingStarted.tex b/docs/theDoc/gettingStarted.tex index e26115ac..493cc4ae 100644 --- a/docs/theDoc/gettingStarted.tex +++ b/docs/theDoc/gettingStarted.tex @@ -2,7 +2,7 @@ \onlyRST{ + **University of Innsbruck**, Austria, Department of Mechatronics -Exudyn now includes a redundant coordinate (constraint) as well as a minimum coordinate formulation (KinematicTree); machine learning and artificial intelligence interface (openAI gym); improved explicit and implicit solvers; sparse matrix support and multi-threading; basic hydraulic actuator; creation of beams along curves; extended robotics modules; contact module; **PlotSensor** for simple post processing, ... See theDoc.pdf chapter **Issues and Bugs** for changes! +Exudyn 1.3 is out! It includes a redundant coordinate (constraint) as well as a minimum coordinate formulation (KinematicTree); machine learning and artificial intelligence interface (openAI gym); improved explicit and implicit solvers; sparse matrix support and multi-threading; basic hydraulic actuator; creation of beams along curves; extended robotics modules; contact module; **PlotSensor** for simple post processing, and some improved 3D visualization, ... See theDoc.pdf chapter **Issues and Bugs** for changes! If you like using Exudyn, please add a *star* on github, and send an email to \ ``reply.exudyn@gmail.com``\ such that we can add you to our newsletter. Let us know, which features you are using or which **features you are missing** and follow us on `Twitter @RExudyn `_ ! @@ -14,22 +14,25 @@ + **pre-built** for Python 3.6, 3.7, 3.8, 3.9, and 3.10 under **Windows** ; Python 3.8 for **MacOS** available; some **Linux** (UBUNTU wheels are available, but at most you should build your wheels by yourself, see instructions in `theDoc.pdf `_ ) + **NOTE**: for pure installation, use **pip install exudyn** (see further description below) -.. |pic1| image:: docs/demo/screenshots/6pistonEngineStresses.jpg - :width: 22% +.. |pic1| image:: docs/demo/screenshots/pistonEngine.gif + :width: 200 -.. |pic2| image:: docs/demo/screenshots/demo4piston.png - :width: 14% +.. |pic2| image:: docs/demo/screenshots/hydraulic2arm.gif + :width: 200 -.. |pic3| image:: docs/demo/screenshots/shaftGear.png - :width: 20% +.. |pic3| image:: docs/demo/screenshots/particles2M.gif + :width: 120 -.. |pic4| image:: docs/demo/screenshots/rotor_runup_plot3.png - :width: 21% +.. |pic4| image:: docs/demo/screenshots/shaftGear.png + :width: 160 -.. |pic5| image:: docs/theDoc/figures/DrawSystemGraphExample.png - :width: 21% +.. |pic5| image:: docs/demo/screenshots/rotor_runup_plot3.png + :width: 190 -|pic1| |pic2| |pic3| |pic4| |pic5| +.. |pic6| image:: docs/theDoc/figures/DrawSystemGraphExample.png + :width: 240 + +|pic1| |pic2| |pic3| |pic4| |pic5| |pic6| This README document is a small part of the complete documentation found as PDF document in docs/theDoc/theDoc.pdf. It is auto-generated from .tex files (sorry for some conversion errors!). diff --git a/docs/theDoc/interfaces.tex b/docs/theDoc/interfaces.tex index b822267c..8f74d6c5 100644 --- a/docs/theDoc/interfaces.tex +++ b/docs/theDoc/interfaces.tex @@ -338,7 +338,7 @@ \begin{longtable}{| p{4.2cm} | p{2.5cm} | p{0.3cm} | p{3.0cm} | p{6cm} |} \hline \bf Name & \bf type / function return type & \bf size & \bf default value / function args & \bf description \\ \hline - autoFitScene & bool & & True & automatically fit scene within first second after StartRenderer()\\ \hline + autoFitScene & bool & & True & automatically fit scene within startup after StartRenderer()\\ \hline axesTiling & PInt & & 12 & global number of segments for drawing axes cylinders and cones (reduce this number, e.g. to 4, if many axes are drawn)\\ \hline backgroundColor & Float4 & 4 & [1.0,1.0,1.0,1.0] & \tabnewline red, green, blue and alpha values for background color of render window (white=[1,1,1,1]; black = [0,0,0,1])\\ \hline backgroundColorBottom & Float4 & 4 & [0.8,0.8,1.0,1.0] & \tabnewline red, green, blue and alpha values for bottom background color in case that useGradientBackground = True\\ \hline @@ -621,16 +621,16 @@ \hline \bf Name & \bf type / function return type & \bf size & \bf default value / function args & \bf description \\ \hline drawFaceNormals & bool & 1 & False & draws triangle normals, e.g. at center of triangles; used for debugging of faces\\ \hline - drawNormalsLength & float & 1 & 0.1 & length of normals; used for debugging\\ \hline + drawNormalsLength & PFloat & 1 & 0.1 & length of normals; used for debugging\\ \hline drawVertexNormals & bool & 1 & False & draws vertex normals; used for debugging\\ \hline enableLight0 & bool & 1 & True & turn on/off light0\\ \hline enableLight1 & bool & 1 & True & turn on/off light1\\ \hline enableLighting & bool & 1 & True & generally enable lighting (otherwise, colors of objects are used); OpenGL: glEnable(GL\_LIGHTING)\\ \hline facesTransparent & bool & 1 & False & True: show faces transparent independent of transparency (A)-value in color of objects; allow to show otherwise hidden node/marker/object numbers\\ \hline initialCenterPoint & Float3 & 3 & [0.,0.,0.] & \tabnewline centerpoint of scene (3D) at renderer startup; overwritten if autoFitScene = True\\ \hline - initialMaxSceneSize & float & & 1. & initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True\\ \hline + initialMaxSceneSize & PFloat & & 1. & initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True\\ \hline initialModelRotation & StdArray33F & 3x3 & [Matrix3DF[3,3,1.,0.,0., 0.,1.,0., 0.,0.,1.]] & \tabnewline initial model rotation matrix for OpenGl; in python use e.g.: initialModelRotation=[[1,0,0],[0,1,0],[0,0,1]]\\ \hline - initialZoom & float & & 1. & initial zoom of scene; overwritten/ignored if autoFitScene = True\\ \hline + initialZoom & UFloat & & 1. & initial zoom of scene; overwritten/ignored if autoFitScene = True\\ \hline light0ambient & float & 1 & 0.3 & ambient value of GL\_LIGHT0\\ \hline light0constantAttenuation & float & 1 & 1.0 & constant attenuation coefficient of GL\_LIGHT0, this is a constant factor that attenuates the light source; attenuation factor = 1/(kx +kl*d + kq*d*d); (kc,kl,kq)=(1,0,0) means no attenuation; only used for lights, where last component of light position is 1\\ \hline light0diffuse & float & 1 & 0.6 & diffuse value of GL\_LIGHT0\\ \hline @@ -649,18 +649,21 @@ lightModelLocalViewer & bool & 1 & False & select local viewer for light; maps to OpenGL glLightModeli(GL\_LIGHT\_MODEL\_LOCAL\_VIEWER,...)\\ \hline lightModelTwoSide & bool & 1 & True & enlighten also backside of object; maps to OpenGL glLightModeli(GL\_LIGHT\_MODEL\_TWO\_SIDE,...)\\ \hline lineSmooth & bool & 1 & True & draw lines smooth\\ \hline - lineWidth & float & 1 & 1. & width of lines used for representation of lines, circles, points, etc.\\ \hline + lineWidth & UFloat & 1 & 1. & width of lines used for representation of lines, circles, points, etc.\\ \hline materialAmbientAndDiffuse & Float4 & 4 & [0.6,0.6,0.6,1.] & \tabnewline 4f ambient color of material\\ \hline materialShininess & float & 1 & 32. & shininess of material\\ \hline materialSpecular & Float4 & 4 & [0.6,0.6,0.6,1.] & \tabnewline 4f specular color of material\\ \hline multiSampling & PInt & 1 & 1 & multi sampling turned off (<=1) or turned on to given values (2, 4, 8 or 16); increases the graphics buffers and might crash due to graphics card memory limitations; only works if supported by hardware; if it does not work, try to change 3D graphics hardware settings!\\ \hline + perspective & UFloat & & 0. & parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective\\ \hline shadeModelSmooth & bool & 1 & True & True: turn on smoothing for shaders, which uses vertex normals to smooth surfaces\\ \hline + shadow & UFloat & & 0. & parameter $\in [0 ... 1]$ prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows\\ \hline + shadowPolygonOffset & PFloat & & 10. & some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize\\ \hline showFaceEdges & bool & 1 & False & show edges of faces; using the options showFaces=false and showFaceEdges=true gives are wire frame representation\\ \hline showFaces & bool & 1 & True & show faces of triangles, etc.; using the options showFaces=false and showFaceEdges=true gives are wire frame representation\\ \hline showMeshEdges & bool & 1 & True & show edges of finite elements; independent of showFaceEdges\\ \hline showMeshFaces & bool & 1 & True & show faces of finite elements; independent of showFaces\\ \hline textLineSmooth & bool & 1 & False & draw lines for representation of text smooth\\ \hline - textLineWidth & float & 1 & 1. & width of lines used for representation of text\\ \hline + textLineWidth & UFloat & 1 & 1. & width of lines used for representation of text\\ \hline \end{longtable} \end{center} @@ -706,6 +709,7 @@ keypressRotationStep & float & & 5. & rotation increment per keypress in degree (full rotation = 360 degree)\\ \hline keypressTranslationStep & float & & 0.1 & translation increment per keypress relative to window size\\ \hline mouseMoveRotationFactor & float & & 1. & rotation increment per 1 pixel mouse movement in degree\\ \hline + selectionHighlights & bool & & True & True: mouse click highlights item (default: red)\\ \hline selectionLeftMouse & bool & & True & True: left mouse click on items and show basic information\\ \hline selectionRightMouse & bool & & True & True: right mouse click on items and show dictionary (read only!)\\ \hline useJoystickInput & bool & & True & True: read joystick input (use 6-axis joystick with lowest ID found when starting renderer window) and interpret as (x,y,z) position and (rotx, roty, rotz) rotation: as available from 3Dconnexion space mouse and maybe others as well; set to False, if external joystick makes problems ...\\ \hline diff --git a/docs/theDoc/pythonUtilitiesDescription.tex b/docs/theDoc/pythonUtilitiesDescription.tex index 30757484..9e1431fd 100644 --- a/docs/theDoc/pythonUtilitiesDescription.tex +++ b/docs/theDoc/pythonUtilitiesDescription.tex @@ -2367,7 +2367,7 @@ \item[]Notes: This is an internal library, which is only used inside Exudyn for modifying settings. \ei \begin{flushleft} -\noindent {def {\bf \exuUrl{https://github.com/jgerstmayr/EXUDYN/blob/master/main/pythonDev/exudyn/GUI.py\#L483}{EditDictionaryWithTypeInfo}{}}}\label{sec:GUI:EditDictionaryWithTypeInfo} +\noindent {def {\bf \exuUrl{https://github.com/jgerstmayr/EXUDYN/blob/master/main/pythonDev/exudyn/GUI.py\#L495}{EditDictionaryWithTypeInfo}{}}}\label{sec:GUI:EditDictionaryWithTypeInfo} ({\it dictionaryData}, {\it exu}= None, {\it dictionaryName}= 'edit') \end{flushleft} \setlength{\itemindent}{0.7cm} diff --git a/docs/theDoc/theDoc.pdf b/docs/theDoc/theDoc.pdf index 93d89838..f8b8f6a6 100644 Binary files a/docs/theDoc/theDoc.pdf and b/docs/theDoc/theDoc.pdf differ diff --git a/docs/theDoc/trackerlog.tex b/docs/theDoc/trackerlog.tex index 31ad462b..8600ce7c 100644 --- a/docs/theDoc/trackerlog.tex +++ b/docs/theDoc/trackerlog.tex @@ -10,15 +10,111 @@ \noindent General information on current version: \bi \small - \item Exudyn version = 1.2.134.dev1, - \item last change = 2022-06-17, - \item Number of issues = 1148, - \item Number of resolved issues = 976 (134 in current version), + \item Exudyn version = 1.3.0, + \item last change = 2022-06-22, + \item Number of issues = 1157, + \item Number of resolved issues = 989 (0 in current version), \ei \mysubsection{Resolved issues and resolved bugs} \par \noindent The following list contains the issues which have been {\bf RESOLVED} in the according version: \bi \footnotesize + \item {\bf Version 1.3.0}: {\bf \color{warningRed} resolved BUG 0677}: {\bf single threaded renderer} + \begin{itemize}[label=$\bullet$] + \item {description: correct crash with visualization dialog (MacOS)} + \item {\bf notes: not resolved, but it is an issue of missing tkinter capabilities in MacOS} + \item date resolved: {\bf 2022-06-22 07:59}, +date raised: 2021-05-12 + \ei + \item {\bf Version 1.2.146}: resolved Issue 0735: {\bf parallel build} +(check) + \begin{itemize}[label=$\bullet$] + \item {description: check parallel build with MSbuild to reduce compilation times} + \item {\bf notes: already done earlier} + \item date resolved: {\bf 2022-06-22 07:58}, +date raised: 2021-08-12 + \ei + \item {\bf Version 1.2.145}: resolved Issue 0863: {\bf RaspberryPi} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: check compilation on Raspi, make adaptation of ngsolve includes to run} + \item {\bf notes: already done earlier} + \item date resolved: {\bf 2022-06-22 07:48}, +date raised: 2022-01-14 + \ei + \item {\bf Version 1.2.144}: resolved Issue 0968: {\bf MarkerBodyCable2DShape} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: add offset from beam axis, to compute position, velocity and jacobians at contact surface} + \item {\bf notes: already done earlier} + \item date resolved: {\bf 2022-06-22 07:46}, +date raised: 2022-03-03 + \ei + \item {\bf Version 1.2.143}: resolved Issue 0972: {\bf ContactFrictionCircleCable2D} +(docu) + \begin{itemize}[label=$\bullet$] + \item {description: add / extend description} + \item date resolved: {\bf 2022-06-22 07:44}, +date raised: 2022-03-09 + \ei + \item {\bf Version 1.2.142}: resolved Issue 1155: {\bf center point} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: add key "o" option to set center point to current center point of view; this allows to rotate around the current center point of the view} + \item date resolved: {\bf 2022-06-21 18:16}, +date raised: 2022-06-21 + \ei + \item {\bf Version 1.2.141}: resolved Issue 1152: {\bf Renderer} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: add separate function to compute accurate scene size, store as 3D vector and as norm} + \item date resolved: {\bf 2022-06-21 17:56}, +date raised: 2022-06-20 + \ei + \item {\bf Version 1.2.140}: resolved Issue 1154: {\bf Zoom all} +(change) + \begin{itemize}[label=$\bullet$] + \item {description: change procedures for zoom all and for computation of maximum scene coordinates; may affect appearance of your models; necessary for consistently computing perspective and shadow parameters} + \item date resolved: {\bf 2022-06-21 08:38}, +date raised: 2022-06-21 + \ei + \item {\bf Version 1.2.139}: resolved Issue 1153: {\bf noglfw} +(check) + \begin{itemize}[label=$\bullet$] + \item {description: check compilation without GLFW} + \item date resolved: {\bf 2022-06-20 10:58}, +date raised: 2022-06-20 + \ei + \item {\bf Version 1.2.138}: resolved Issue 1150: {\bf OpenGL} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: add shadows (simple)} + \item {\bf notes: activate with SC.VisualizationSettings().openGL.shadow, chosing a value between 0. and 1; good results obtained with 0.5} + \item date resolved: {\bf 2022-06-20 01:49}, +date raised: 2022-06-18 + \ei + \item {\bf Version 1.2.137}: resolved Issue 1151: {\bf linux builds} +(change) + \begin{itemize}[label=$\bullet$] + \item {description: remove -g flag from linux builds, leading to 2.6MB instead of 38MB binaries; to enable debug information (e.g. to detect origin of some crashes, remove the -g0 flag in setup.py)} + \item date resolved: {\bf 2022-06-19 18:34}, +date raised: 2022-06-19 + \ei + \item {\bf Version 1.2.136}: resolved Issue 1149: {\bf OpenGL} +(extension) + \begin{itemize}[label=$\bullet$] + \item {description: add perspective} + \item {\bf notes: added openGL option perspective; EXPERIMENTAL!} + \item date resolved: {\bf 2022-06-19 01:59}, +date raised: 2022-06-18 + \ei + \item {\bf Version 1.2.135}: resolved Issue 1148: {\bf jacobian ODE1 ODE2} +(fix) + \begin{itemize}[label=$\bullet$] + \item {description: fix jacobian computations for mixed ODE1-ODE2 components; check with HydraulicActuatorSimple (lower number of jacobians and iterations)} + \item date resolved: {\bf 2022-06-18 23:38}, +date raised: 2022-06-18 + \ei \item {\bf Version 1.2.134}: resolved Issue 1147: {\bf ODE1Coordinates\_t} (extension) \begin{itemize}[label=$\bullet$] @@ -4345,11 +4441,6 @@ \item {description: modified Newton does not work, no Jacobian update computed when switching} \item date raised: 2021-08-13 \ei - \item open {\bf BUG 0677}: {\bf single threaded renderer} - \begin{itemize}[label=$\bullet$] - \item {description: correct crash with visualization dialog (MacOS)} - \item date raised: 2021-05-12 - \ei \item open {\bf BUG 0448}: {\bf ObjectGenericODE2 bug} \begin{itemize}[label=$\bullet$] \item {description: ObjectGenericODE2 crashes without message when initialized with invalid node numbers} diff --git a/docs/theDoc/version.tex b/docs/theDoc/version.tex index 6ee41562..817b17d8 100644 --- a/docs/theDoc/version.tex +++ b/docs/theDoc/version.tex @@ -1,3 +1,3 @@ % version info automatically generated by tracker; generated by Johannes Gerstmayr -% last modified = 2022-06-17 -Exudyn version = 1.2.134.dev1 (Corea) +% last modified = 2022-06-22 +Exudyn version = 1.3.0 (Davis) diff --git a/docs/trackerlog.html b/docs/trackerlog.html index 8aa554af..45e895b5 100644 --- a/docs/trackerlog.html +++ b/docs/trackerlog.html @@ -15,10 +15,10 @@

ISSUE Tracker

-Number of issues = 1148, -Number of resolved issues = 976 (134 in current minor version), -Exudyn version = 1.2.134.dev1, -last change = 2022-06-17 +Number of issues = 1157, +Number of resolved issues = 989 (0 in current minor version), +Exudyn version = 1.3.0, +last change = 2022-06-22 @@ -38,6 +38,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + @@ -534,22 +550,6 @@

ISSUE Tracker

- - - - - - - - - - - - - - - - @@ -566,22 +566,6 @@

ISSUE Tracker

- - - - - - - - - - - - - - - - @@ -1014,22 +998,6 @@

ISSUE Tracker

- - - - - - - - - - - - - - - - @@ -1654,22 +1622,6 @@

ISSUE Tracker

- - - - - - - - - - - - - - - - @@ -1782,22 +1734,6 @@

ISSUE Tracker

- - - - - - - - - - - - - - - - @@ -2790,6 +2726,134 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5094,6 +5158,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + @@ -5126,6 +5206,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + @@ -6358,6 +6454,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + @@ -7766,6 +7878,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + @@ -8566,6 +8694,22 @@

ISSUE Tracker

+ + + + + + + + + + + + + + + + diff --git a/main/pythonDev/Examples/HydraulicActuator2Arms.py b/main/pythonDev/Examples/HydraulicActuator2Arms.py index 7232d5d5..76890f14 100644 --- a/main/pythonDev/Examples/HydraulicActuator2Arms.py +++ b/main/pythonDev/Examples/HydraulicActuator2Arms.py @@ -258,6 +258,7 @@ def PreStepUserFunction(mbs, t): SC.visualizationSettings.openGL.multiSampling = 4 SC.visualizationSettings.openGL.lineWidth = 2 +SC.visualizationSettings.openGL.shadow = 0.5 SC.visualizationSettings.window.renderWindowSize = [1600,1200] exu.StartRenderer() diff --git a/main/pythonDev/Examples/rigid3Dexample.py b/main/pythonDev/Examples/rigid3Dexample.py index 55b89279..3f5efc85 100644 --- a/main/pythonDev/Examples/rigid3Dexample.py +++ b/main/pythonDev/Examples/rigid3Dexample.py @@ -30,7 +30,7 @@ #create background, in order to have according zoom all # background0 = GraphicsDataRectangle(-zz,-2*zz,zz,zz,color4white) -background0 = GraphicsDataCheckerBoard(point=[0,-0.5*zz,-zz],size=4*zz) +background0 = GraphicsDataCheckerBoard(point=[0,-0.5*zz,-0.25*zz],size=6*zz) oGround=mbs.AddObject(ObjectGround(referencePosition= [0,0,0], visualization=VObjectGround(graphicsData= [background0]))) mPosLast = mbs.AddMarker(MarkerBodyPosition(bodyNumber = oGround, @@ -93,6 +93,10 @@ SC.visualizationSettings.openGL.multiSampling = 4 SC.visualizationSettings.openGL.lineWidth = 2 +# uncomment following line for shadow: +# SC.visualizationSettings.openGL.shadow = 0.5 +# SC.visualizationSettings.openGL.light0position = [4,4,10,0] + exu.StartRenderer() mbs.WaitForUserToContinue() diff --git a/main/pythonDev/TestModels/generalContactFrictionTests.py b/main/pythonDev/TestModels/generalContactFrictionTests.py index 253c2ac9..1468e82a 100644 --- a/main/pythonDev/TestModels/generalContactFrictionTests.py +++ b/main/pythonDev/TestModels/generalContactFrictionTests.py @@ -382,7 +382,8 @@ def UFtorque(mbs, t, loadVector): SC.visualizationSettings.openGL.drawFaceNormals = False SC.visualizationSettings.openGL.multiSampling = 4 - +SC.visualizationSettings.openGL.shadow = 0.25 +SC.visualizationSettings.openGL.light0position = [-3,3,10,0] if useGraphics: SC.visualizationSettings.general.autoFitScene = False diff --git a/main/pythonDev/TestModels/runPerformanceTests.py b/main/pythonDev/TestModels/runPerformanceTests.py index 3d36dcc8..8cdb0a9e 100644 --- a/main/pythonDev/TestModels/runPerformanceTests.py +++ b/main/pythonDev/TestModels/runPerformanceTests.py @@ -17,6 +17,7 @@ if sys.version_info.major != 3 or sys.version_info.minor < 6:# or sys.version_info.minor > 9: raise ImportError("EXUDYN only supports python versions >= 3.6") isMacOS = (sys.platform == 'darwin') +isWindows = (sys.platform == 'win32') #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #include right exudyn module now: @@ -90,6 +91,8 @@ def NumTo2digits(n): platformString += 'P'+str(sys.version_info.major) +'.'+ str(sys.version_info.minor) if isMacOS: platformString += 'MacOSX' +elif not isWindows: #add linux, to distinguish linux tests from windows tests! + platformString += sys.platform subFolder = '' if platform.processor() == 'Intel64 Family 6 Model 142 Stepping 10, GenuineIntel': @@ -106,6 +109,7 @@ def NumTo2digits(n): exu.Print('EXUDYN version = '+exu.GetVersionString()) exu.Print('EXUDYN build date = '+exuDateStr) exu.Print('platform = '+platform.architecture()[0]) +exu.Print('system = '+sys.platform) #Surface book 2 = 'Intel64 Family 6 Model 142 Stepping 10, GenuineIntel' exu.Print('processor = '+platform.processor()) diff --git a/main/pythonDev/TestModels/runTestSuiteRefSol.py b/main/pythonDev/TestModels/runTestSuiteRefSol.py index 1188f303..6165002a 100644 --- a/main/pythonDev/TestModels/runTestSuiteRefSol.py +++ b/main/pythonDev/TestModels/runTestSuiteRefSol.py @@ -45,7 +45,7 @@ def TestExamplesReferenceSolution(): 'geneticOptimizationTest.py':0.10117518366826603, #before 2022-02-20 (accuracy of internal sensors is higher); 0.10117518367051619, #changed to some analytic Connector jacobians (CartSpringDamper), implicit solver(modified Newton restart, etc.); before 2022-01-18: 0.10117518366934351, 'geometricallyExactBeam2Dtest.py':-2.2115028353806547, 'heavyTop.py':33.423125751743804, - 'hydraulicActuatorSimpleTest.py':7.130437437122315, + 'hydraulicActuatorSimpleTest.py':7.130440021870293, 'kinematicTreeAndMBStest.py':2.6388120463802767e-05, #original but too sensitive to disturbances: 263.88120463802767, 'kinematicTreeConstraintTest.py':1.8135975384620484 , 'kinematicTreeTest.py': -1.309383960216414, diff --git a/main/pythonDev/exudyn/GUI.py b/main/pythonDev/exudyn/GUI.py index 106ab6fb..8b9d7a0d 100644 --- a/main/pythonDev/exudyn/GUI.py +++ b/main/pythonDev/exudyn/GUI.py @@ -105,7 +105,19 @@ def ConvertString2Value(value, vType, vSize, dictionaryTypesT): else: return [False, errorMsg] - if vType == 'float': + if (vType == 'float' + or vType == 'PReal' or vType == 'UReal' + or vType == 'PFloat' or vType == 'UFloat'): + floatValue = float(value) + if vType == 'PReal' and floatValue <= 0: + errorMsg = 'PReal must be > 0' + if vType == 'UReal' and floatValue < 0: + errorMsg = 'UReal must be >= 0' + if vType == 'PFloat' and floatValue <= 0: + errorMsg = 'PFloat must be > 0' + if vType == 'UFloat' and floatValue < 0: + errorMsg = 'UFloat must be >= 0' + return [float(value), errorMsg] if vType == 'Index' or vType == 'Int' or vType == 'PInt' or vType == 'UInt': diff --git a/main/setup.py b/main/setup.py index 6536c043..7dafc09a 100644 --- a/main/setup.py +++ b/main/setup.py @@ -386,6 +386,7 @@ class BuildExt(build_ext): '-Wno-unknown-pragmas', #warning from ngs_core.hpp/taskmanager.hpp (NGsolve) '-Wno-sign-compare', #warning from taskmanager.hpp (NGsolve) '-Wall', + '-g0', #deactivate debug information (overrides default -g flags), decreases files size from 38MB to 2.6 MB in Python 3.6 version '-D'+exudynPythonMacro, #'-std=c++17', #==>chosen automatic #'-fpermissive', #because of exceptions ==> allows compilation diff --git a/main/src/Autogenerated/BeamSectionGeometry.h b/main/src/Autogenerated/BeamSectionGeometry.h index 32b2f10d..5e668cb8 100644 --- a/main/src/Autogenerated/BeamSectionGeometry.h +++ b/main/src/Autogenerated/BeamSectionGeometry.h @@ -4,7 +4,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/CSolverStructures.h b/main/src/Autogenerated/CSolverStructures.h index 46a6bea6..862856ae 100644 --- a/main/src/Autogenerated/CSolverStructures.h +++ b/main/src/Autogenerated/CSolverStructures.h @@ -4,7 +4,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -136,7 +136,7 @@ class CSolverTimer // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -260,7 +260,7 @@ class SolverLocalData // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -374,7 +374,7 @@ class SolverIterationData // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -470,7 +470,7 @@ class SolverConvergenceData // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -573,7 +573,7 @@ class SolverOutputData // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/DictionariesGetSet.h b/main/src/Autogenerated/DictionariesGetSet.h index 1b435e52..6897d0ec 100644 --- a/main/src/Autogenerated/DictionariesGetSet.h +++ b/main/src/Autogenerated/DictionariesGetSet.h @@ -2,7 +2,7 @@ // AUTO: Helper file for dictionaries get/set for system structures; generated by Johannes Gerstmayr // AUTO: Generated by Johannes Gerstmayr // AUTO: Used for SimulationSettings and VisualizationSettings -// AUTO: last modified = 2022-06-16 +// AUTO: last modified = 2022-06-21 // AUTO: ++++++++++++++++++++++ #ifndef DICTIONARIESGETSET__H @@ -1186,7 +1186,7 @@ d["value"] = data.autoFitScene; d["type"] = "bool"; d["size"] = std::vector{1}; - d["description"] = "automatically fit scene within first second after StartRenderer()"; + d["description"] = "automatically fit scene within startup after StartRenderer()"; structureDict["autoFitScene"] = d; d = py::dict(); //reset local dict @@ -2293,8 +2293,8 @@ d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item - d["value"] = data.drawNormalsLength; - d["type"] = "float"; + d["value"] = data.PyGetDrawNormalsLength(); + d["type"] = "PFloat"; d["size"] = std::vector{1}; d["description"] = "length of normals; used for debugging"; structureDict["drawNormalsLength"] = d; @@ -2349,8 +2349,8 @@ d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item - d["value"] = data.initialMaxSceneSize; - d["type"] = "float"; + d["value"] = data.PyGetInitialMaxSceneSize(); + d["type"] = "PFloat"; d["size"] = std::vector{1}; d["description"] = "initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True"; structureDict["initialMaxSceneSize"] = d; @@ -2365,8 +2365,8 @@ d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item - d["value"] = data.initialZoom; - d["type"] = "float"; + d["value"] = data.PyGetInitialZoom(); + d["type"] = "UFloat"; d["size"] = std::vector{1}; d["description"] = "initial zoom of scene; overwritten/ignored if autoFitScene = True"; structureDict["initialZoom"] = d; @@ -2517,8 +2517,8 @@ d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item - d["value"] = data.lineWidth; - d["type"] = "float"; + d["value"] = data.PyGetLineWidth(); + d["type"] = "UFloat"; d["size"] = std::vector{1}; d["description"] = "width of lines used for representation of lines, circles, points, etc."; structureDict["lineWidth"] = d; @@ -2555,6 +2555,14 @@ d["description"] = "multi sampling turned off (<=1) or turned on to given values (2, 4, 8 or 16); increases the graphics buffers and might crash due to graphics card memory limitations; only works if supported by hardware; if it does not work, try to change 3D graphics hardware settings!"; structureDict["multiSampling"] = d; + d = py::dict(); //reset local dict + d["itemIdentifier"] = std::string(""); //identifier for item + d["value"] = data.PyGetPerspective(); + d["type"] = "UFloat"; + d["size"] = std::vector{1}; + d["description"] = "parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective"; + structureDict["perspective"] = d; + d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item d["value"] = data.shadeModelSmooth; @@ -2563,6 +2571,22 @@ d["description"] = "True: turn on smoothing for shaders, which uses vertex normals to smooth surfaces"; structureDict["shadeModelSmooth"] = d; + d = py::dict(); //reset local dict + d["itemIdentifier"] = std::string(""); //identifier for item + d["value"] = data.PyGetShadow(); + d["type"] = "UFloat"; + d["size"] = std::vector{1}; + d["description"] = "parameter \\in [0 ... 1] prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows"; + structureDict["shadow"] = d; + + d = py::dict(); //reset local dict + d["itemIdentifier"] = std::string(""); //identifier for item + d["value"] = data.PyGetShadowPolygonOffset(); + d["type"] = "PFloat"; + d["size"] = std::vector{1}; + d["description"] = "some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize"; + structureDict["shadowPolygonOffset"] = d; + d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item d["value"] = data.showFaceEdges; @@ -2605,8 +2629,8 @@ d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item - d["value"] = data.textLineWidth; - d["type"] = "float"; + d["value"] = data.PyGetTextLineWidth(); + d["type"] = "UFloat"; d["size"] = std::vector{1}; d["description"] = "width of lines used for representation of text"; structureDict["textLineWidth"] = d; @@ -2649,7 +2673,10 @@ data.materialShininess = py::cast(d["materialShininess"]); data.materialSpecular = py::cast>(d["materialSpecular"]); data.multiSampling = py::cast(d["multiSampling"]); + data.perspective = py::cast(d["perspective"]); data.shadeModelSmooth = py::cast(d["shadeModelSmooth"]); + data.shadow = py::cast(d["shadow"]); + data.shadowPolygonOffset = py::cast(d["shadowPolygonOffset"]); data.showFaceEdges = py::cast(d["showFaceEdges"]); data.showFaces = py::cast(d["showFaces"]); data.showMeshEdges = py::cast(d["showMeshEdges"]); @@ -2813,6 +2840,14 @@ d["description"] = "rotation increment per 1 pixel mouse movement in degree"; structureDict["mouseMoveRotationFactor"] = d; + d = py::dict(); //reset local dict + d["itemIdentifier"] = std::string(""); //identifier for item + d["value"] = data.selectionHighlights; + d["type"] = "bool"; + d["size"] = std::vector{1}; + d["description"] = "True: mouse click highlights item (default: red)"; + structureDict["selectionHighlights"] = d; + d = py::dict(); //reset local dict d["itemIdentifier"] = std::string(""); //identifier for item d["value"] = data.selectionLeftMouse; @@ -2859,6 +2894,7 @@ data.keypressRotationStep = py::cast(d["keypressRotationStep"]); data.keypressTranslationStep = py::cast(d["keypressTranslationStep"]); data.mouseMoveRotationFactor = py::cast(d["mouseMoveRotationFactor"]); + data.selectionHighlights = py::cast(d["selectionHighlights"]); data.selectionLeftMouse = py::cast(d["selectionLeftMouse"]); data.selectionRightMouse = py::cast(d["selectionRightMouse"]); data.useJoystickInput = py::cast(d["useJoystickInput"]); diff --git a/main/src/Autogenerated/MainSolver.h b/main/src/Autogenerated/MainSolver.h index 0ad29cdb..fa90e334 100644 --- a/main/src/Autogenerated/MainSolver.h +++ b/main/src/Autogenerated/MainSolver.h @@ -7,7 +7,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -93,7 +93,7 @@ class MainSolverStatic: public MainSolverBase // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -263,7 +263,7 @@ class MainSolverImplicitSecondOrder: public MainSolverBase // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/PyStructuralElementsDataStructures.h b/main/src/Autogenerated/PyStructuralElementsDataStructures.h index e44d52da..1bd149e7 100644 --- a/main/src/Autogenerated/PyStructuralElementsDataStructures.h +++ b/main/src/Autogenerated/PyStructuralElementsDataStructures.h @@ -4,7 +4,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/Pybind_modules.h b/main/src/Autogenerated/Pybind_modules.h index d7b62e5c..bab3d36f 100644 --- a/main/src/Autogenerated/Pybind_modules.h +++ b/main/src/Autogenerated/Pybind_modules.h @@ -1,6 +1,6 @@ // AUTO: ++++++++++++++++++++++ // AUTO: pybind11 module includes; generated by Johannes Gerstmayr -// AUTO: last modified = 2022-06-16 +// AUTO: last modified = 2022-06-21 // AUTO: ++++++++++++++++++++++ //++++++++++++++++++++++++++++++++ @@ -245,7 +245,7 @@ //++++++++++++++++++++++++++++++++ py::class_(m, "VSettingsGeneral", "VSettingsGeneral class") // AUTO: .def(py::init<>()) - .def_readwrite("autoFitScene", &VSettingsGeneral::autoFitScene, "automatically fit scene within first second after StartRenderer()") + .def_readwrite("autoFitScene", &VSettingsGeneral::autoFitScene, "automatically fit scene within startup after StartRenderer()") .def_property("axesTiling", &VSettingsGeneral::PyGetAxesTiling, &VSettingsGeneral::PySetAxesTiling) .def_property("backgroundColor", &VSettingsGeneral::PyGetBackgroundColor, &VSettingsGeneral::PySetBackgroundColor) .def_property("backgroundColorBottom", &VSettingsGeneral::PyGetBackgroundColorBottom, &VSettingsGeneral::PySetBackgroundColorBottom) @@ -456,16 +456,16 @@ py::class_(m, "VSettingsOpenGL", "VSettingsOpenGL class") // AUTO: .def(py::init<>()) .def_readwrite("drawFaceNormals", &VSettingsOpenGL::drawFaceNormals, "draws triangle normals, e.g. at center of triangles; used for debugging of faces") - .def_readwrite("drawNormalsLength", &VSettingsOpenGL::drawNormalsLength, "length of normals; used for debugging") + .def_property("drawNormalsLength", &VSettingsOpenGL::PyGetDrawNormalsLength, &VSettingsOpenGL::PySetDrawNormalsLength) .def_readwrite("drawVertexNormals", &VSettingsOpenGL::drawVertexNormals, "draws vertex normals; used for debugging") .def_readwrite("enableLight0", &VSettingsOpenGL::enableLight0, "turn on/off light0") .def_readwrite("enableLight1", &VSettingsOpenGL::enableLight1, "turn on/off light1") .def_readwrite("enableLighting", &VSettingsOpenGL::enableLighting, "generally enable lighting (otherwise, colors of objects are used); OpenGL: glEnable(GL_LIGHTING)") .def_readwrite("facesTransparent", &VSettingsOpenGL::facesTransparent, "True: show faces transparent independent of transparency (A)-value in color of objects; allow to show otherwise hidden node/marker/object numbers") .def_property("initialCenterPoint", &VSettingsOpenGL::PyGetInitialCenterPoint, &VSettingsOpenGL::PySetInitialCenterPoint) - .def_readwrite("initialMaxSceneSize", &VSettingsOpenGL::initialMaxSceneSize, "initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True") + .def_property("initialMaxSceneSize", &VSettingsOpenGL::PyGetInitialMaxSceneSize, &VSettingsOpenGL::PySetInitialMaxSceneSize) .def_readwrite("initialModelRotation", &VSettingsOpenGL::initialModelRotation, "initial model rotation matrix for OpenGl; in python use e.g.: initialModelRotation=[[1,0,0],[0,1,0],[0,0,1]]") - .def_readwrite("initialZoom", &VSettingsOpenGL::initialZoom, "initial zoom of scene; overwritten/ignored if autoFitScene = True") + .def_property("initialZoom", &VSettingsOpenGL::PyGetInitialZoom, &VSettingsOpenGL::PySetInitialZoom) .def_readwrite("light0ambient", &VSettingsOpenGL::light0ambient, "ambient value of GL_LIGHT0") .def_readwrite("light0constantAttenuation", &VSettingsOpenGL::light0constantAttenuation, "constant attenuation coefficient of GL_LIGHT0, this is a constant factor that attenuates the light source; attenuation factor = 1/(kx +kl*d + kq*d*d); (kc,kl,kq)=(1,0,0) means no attenuation; only used for lights, where last component of light position is 1") .def_readwrite("light0diffuse", &VSettingsOpenGL::light0diffuse, "diffuse value of GL_LIGHT0") @@ -484,18 +484,21 @@ .def_readwrite("lightModelLocalViewer", &VSettingsOpenGL::lightModelLocalViewer, "select local viewer for light; maps to OpenGL glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,...)") .def_readwrite("lightModelTwoSide", &VSettingsOpenGL::lightModelTwoSide, "enlighten also backside of object; maps to OpenGL glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,...)") .def_readwrite("lineSmooth", &VSettingsOpenGL::lineSmooth, "draw lines smooth") - .def_readwrite("lineWidth", &VSettingsOpenGL::lineWidth, "width of lines used for representation of lines, circles, points, etc.") + .def_property("lineWidth", &VSettingsOpenGL::PyGetLineWidth, &VSettingsOpenGL::PySetLineWidth) .def_property("materialAmbientAndDiffuse", &VSettingsOpenGL::PyGetMaterialAmbientAndDiffuse, &VSettingsOpenGL::PySetMaterialAmbientAndDiffuse) .def_readwrite("materialShininess", &VSettingsOpenGL::materialShininess, "shininess of material") .def_property("materialSpecular", &VSettingsOpenGL::PyGetMaterialSpecular, &VSettingsOpenGL::PySetMaterialSpecular) .def_property("multiSampling", &VSettingsOpenGL::PyGetMultiSampling, &VSettingsOpenGL::PySetMultiSampling) + .def_property("perspective", &VSettingsOpenGL::PyGetPerspective, &VSettingsOpenGL::PySetPerspective) .def_readwrite("shadeModelSmooth", &VSettingsOpenGL::shadeModelSmooth, "True: turn on smoothing for shaders, which uses vertex normals to smooth surfaces") + .def_property("shadow", &VSettingsOpenGL::PyGetShadow, &VSettingsOpenGL::PySetShadow) + .def_property("shadowPolygonOffset", &VSettingsOpenGL::PyGetShadowPolygonOffset, &VSettingsOpenGL::PySetShadowPolygonOffset) .def_readwrite("showFaceEdges", &VSettingsOpenGL::showFaceEdges, "show edges of faces; using the options showFaces=false and showFaceEdges=true gives are wire frame representation") .def_readwrite("showFaces", &VSettingsOpenGL::showFaces, "show faces of triangles, etc.; using the options showFaces=false and showFaceEdges=true gives are wire frame representation") .def_readwrite("showMeshEdges", &VSettingsOpenGL::showMeshEdges, "show edges of finite elements; independent of showFaceEdges") .def_readwrite("showMeshFaces", &VSettingsOpenGL::showMeshFaces, "show faces of finite elements; independent of showFaces") .def_readwrite("textLineSmooth", &VSettingsOpenGL::textLineSmooth, "draw lines for representation of text smooth") - .def_readwrite("textLineWidth", &VSettingsOpenGL::textLineWidth, "width of lines used for representation of text") + .def_property("textLineWidth", &VSettingsOpenGL::PyGetTextLineWidth, &VSettingsOpenGL::PySetTextLineWidth) // AUTO: access functions for VSettingsOpenGL .def("__repr__", [](const VSettingsOpenGL &item) { return ""; } ) //!< AUTO: add representation for object based on ostream operator ; // AUTO: end of class definition!!! @@ -529,6 +532,7 @@ .def_readwrite("keypressRotationStep", &VSettingsInteractive::keypressRotationStep, "rotation increment per keypress in degree (full rotation = 360 degree)") .def_readwrite("keypressTranslationStep", &VSettingsInteractive::keypressTranslationStep, "translation increment per keypress relative to window size") .def_readwrite("mouseMoveRotationFactor", &VSettingsInteractive::mouseMoveRotationFactor, "rotation increment per 1 pixel mouse movement in degree") + .def_readwrite("selectionHighlights", &VSettingsInteractive::selectionHighlights, "True: mouse click highlights item (default: red)") .def_readwrite("selectionLeftMouse", &VSettingsInteractive::selectionLeftMouse, "True: left mouse click on items and show basic information") .def_readwrite("selectionRightMouse", &VSettingsInteractive::selectionRightMouse, "True: right mouse click on items and show dictionary (read only!)") .def_readwrite("useJoystickInput", &VSettingsInteractive::useJoystickInput, "True: read joystick input (use 6-axis joystick with lowest ID found when starting renderer window) and interpret as (x,y,z) position and (rotx, roty, rotz) rotation: as available from 3Dconnexion space mouse and maybe others as well; set to False, if external joystick makes problems ...") diff --git a/main/src/Autogenerated/SimulationSettings.h b/main/src/Autogenerated/SimulationSettings.h index b3d03407..e35bf0cf 100644 --- a/main/src/Autogenerated/SimulationSettings.h +++ b/main/src/Autogenerated/SimulationSettings.h @@ -4,7 +4,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -153,7 +153,7 @@ class SolutionSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -233,7 +233,7 @@ class NumericalDifferentiationSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -301,7 +301,7 @@ class DiscontinuousSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -431,7 +431,7 @@ class NewtonSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -513,7 +513,7 @@ class GeneralizedAlphaSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -574,7 +574,7 @@ class ExplicitIntegrationSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -787,7 +787,7 @@ class TimeIntegrationSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -953,7 +953,7 @@ class StaticSolverSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1019,7 +1019,7 @@ class LinearSolverSettings // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1094,7 +1094,7 @@ class Parallel // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/VisualizationSettings.h b/main/src/Autogenerated/VisualizationSettings.h index e5f6bece..a64c3d12 100644 --- a/main/src/Autogenerated/VisualizationSettings.h +++ b/main/src/Autogenerated/VisualizationSettings.h @@ -4,7 +4,7 @@ * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -26,7 +26,7 @@ class VSettingsGeneral // AUTO: { public: // AUTO: - bool autoFitScene; //!< AUTO: automatically fit scene within first second after StartRenderer() + bool autoFitScene; //!< AUTO: automatically fit scene within startup after StartRenderer() Index axesTiling; //!< AUTO: global number of segments for drawing axes cylinders and cones (reduce this number, e.g. to 4, if many axes are drawn) Float4 backgroundColor; //!< AUTO: red, green, blue and alpha values for background color of render window (white=[1,1,1,1]; black = [0,0,0,1]) Float4 backgroundColorBottom; //!< AUTO: red, green, blue and alpha values for bottom background color in case that useGradientBackground = True @@ -185,7 +185,7 @@ class VSettingsGeneral // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -277,7 +277,7 @@ class VSettingsContour // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -368,7 +368,7 @@ class VSettingsNodes // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -459,7 +459,7 @@ class VSettingsBeams // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -520,7 +520,7 @@ class VSettingsKinematicTree // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -598,7 +598,7 @@ class VSettingsBodies // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -687,7 +687,7 @@ class VSettingsConnectors // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -756,7 +756,7 @@ class VSettingsMarkers // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -834,7 +834,7 @@ class VSettingsLoads // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -903,7 +903,7 @@ class VSettingsSensors // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -989,7 +989,7 @@ class VSettingsContact // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1076,7 +1076,7 @@ class VSettingsWindow // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1128,7 +1128,10 @@ class VSettingsOpenGL // AUTO: float materialShininess; //!< AUTO: shininess of material Float4 materialSpecular; //!< AUTO: 4f specular color of material Index multiSampling; //!< AUTO: multi sampling turned off (<=1) or turned on to given values (2, 4, 8 or 16); increases the graphics buffers and might crash due to graphics card memory limitations; only works if supported by hardware; if it does not work, try to change 3D graphics hardware settings! + float perspective; //!< AUTO: parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective bool shadeModelSmooth; //!< AUTO: True: turn on smoothing for shaders, which uses vertex normals to smooth surfaces + float shadow; //!< AUTO: parameter \f$\in [0 ... 1]\f$ prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows + float shadowPolygonOffset; //!< AUTO: some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize bool showFaceEdges; //!< AUTO: show edges of faces; using the options showFaces=false and showFaceEdges=true gives are wire frame representation bool showFaces; //!< AUTO: show faces of triangles, etc.; using the options showFaces=false and showFaceEdges=true gives are wire frame representation bool showMeshEdges; //!< AUTO: show edges of finite elements; independent of showFaceEdges @@ -1175,7 +1178,10 @@ class VSettingsOpenGL // AUTO: materialShininess = 32.f; materialSpecular = Float4({0.6f,0.6f,0.6f,1.f}); multiSampling = 1; + perspective = 0.f; shadeModelSmooth = true; + shadow = 0.f; + shadowPolygonOffset = 10.f; showFaceEdges = false; showFaces = true; showMeshEdges = true; @@ -1185,11 +1191,26 @@ class VSettingsOpenGL // AUTO: }; // AUTO: access functions + //! AUTO: Set function (needed in pybind) for: length of normals; used for debugging + void PySetDrawNormalsLength(const float& drawNormalsLengthInit) { drawNormalsLength = EXUstd::GetSafelyPFloat(drawNormalsLengthInit,"drawNormalsLength"); } + //! AUTO: Read (Copy) access to: length of normals; used for debugging + float PyGetDrawNormalsLength() const { return float(drawNormalsLength); } + //! AUTO: Set function (needed in pybind) for: centerpoint of scene (3D) at renderer startup; overwritten if autoFitScene = True void PySetInitialCenterPoint(const std::array& initialCenterPointInit) { initialCenterPoint = initialCenterPointInit; } //! AUTO: Read (Copy) access to: centerpoint of scene (3D) at renderer startup; overwritten if autoFitScene = True std::array PyGetInitialCenterPoint() const { return std::array(initialCenterPoint); } + //! AUTO: Set function (needed in pybind) for: initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True + void PySetInitialMaxSceneSize(const float& initialMaxSceneSizeInit) { initialMaxSceneSize = EXUstd::GetSafelyPFloat(initialMaxSceneSizeInit,"initialMaxSceneSize"); } + //! AUTO: Read (Copy) access to: initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True + float PyGetInitialMaxSceneSize() const { return float(initialMaxSceneSize); } + + //! AUTO: Set function (needed in pybind) for: initial zoom of scene; overwritten/ignored if autoFitScene = True + void PySetInitialZoom(const float& initialZoomInit) { initialZoom = EXUstd::GetSafelyUFloat(initialZoomInit,"initialZoom"); } + //! AUTO: Read (Copy) access to: initial zoom of scene; overwritten/ignored if autoFitScene = True + float PyGetInitialZoom() const { return float(initialZoom); } + //! AUTO: Set function (needed in pybind) for: 4f position vector of GL\_LIGHT0; 4th value should be 0 for lights like sun, but 1 for directional lights (and for attenuation factor being calculated); see opengl manuals void PySetLight0position(const std::array& light0positionInit) { light0position = light0positionInit; } //! AUTO: Read (Copy) access to: 4f position vector of GL\_LIGHT0; 4th value should be 0 for lights like sun, but 1 for directional lights (and for attenuation factor being calculated); see opengl manuals @@ -1205,6 +1226,11 @@ class VSettingsOpenGL // AUTO: //! AUTO: Read (Copy) access to: global ambient light; maps to OpenGL glLightModeli(GL\_LIGHT\_MODEL\_AMBIENT,[r,g,b,a]) std::array PyGetLightModelAmbient() const { return std::array(lightModelAmbient); } + //! AUTO: Set function (needed in pybind) for: width of lines used for representation of lines, circles, points, etc. + void PySetLineWidth(const float& lineWidthInit) { lineWidth = EXUstd::GetSafelyUFloat(lineWidthInit,"lineWidth"); } + //! AUTO: Read (Copy) access to: width of lines used for representation of lines, circles, points, etc. + float PyGetLineWidth() const { return float(lineWidth); } + //! AUTO: Set function (needed in pybind) for: 4f ambient color of material void PySetMaterialAmbientAndDiffuse(const std::array& materialAmbientAndDiffuseInit) { materialAmbientAndDiffuse = materialAmbientAndDiffuseInit; } //! AUTO: Read (Copy) access to: 4f ambient color of material @@ -1220,6 +1246,26 @@ class VSettingsOpenGL // AUTO: //! AUTO: Read (Copy) access to: multi sampling turned off (<=1) or turned on to given values (2, 4, 8 or 16); increases the graphics buffers and might crash due to graphics card memory limitations; only works if supported by hardware; if it does not work, try to change 3D graphics hardware settings! Index PyGetMultiSampling() const { return Index(multiSampling); } + //! AUTO: Set function (needed in pybind) for: parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective + void PySetPerspective(const float& perspectiveInit) { perspective = EXUstd::GetSafelyUFloat(perspectiveInit,"perspective"); } + //! AUTO: Read (Copy) access to: parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective + float PyGetPerspective() const { return float(perspective); } + + //! AUTO: Set function (needed in pybind) for: parameter \f$\in [0 ... 1]\f$ prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows + void PySetShadow(const float& shadowInit) { shadow = EXUstd::GetSafelyUFloat(shadowInit,"shadow"); } + //! AUTO: Read (Copy) access to: parameter \f$\in [0 ... 1]\f$ prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows + float PyGetShadow() const { return float(shadow); } + + //! AUTO: Set function (needed in pybind) for: some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize + void PySetShadowPolygonOffset(const float& shadowPolygonOffsetInit) { shadowPolygonOffset = EXUstd::GetSafelyPFloat(shadowPolygonOffsetInit,"shadowPolygonOffset"); } + //! AUTO: Read (Copy) access to: some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize + float PyGetShadowPolygonOffset() const { return float(shadowPolygonOffset); } + + //! AUTO: Set function (needed in pybind) for: width of lines used for representation of text + void PySetTextLineWidth(const float& textLineWidthInit) { textLineWidth = EXUstd::GetSafelyUFloat(textLineWidthInit,"textLineWidth"); } + //! AUTO: Read (Copy) access to: width of lines used for representation of text + float PyGetTextLineWidth() const { return float(textLineWidth); } + //! AUTO: print function used in ostream operator (print is virtual and can thus be overloaded) virtual void Print(std::ostream& os) const { @@ -1260,7 +1306,10 @@ class VSettingsOpenGL // AUTO: os << " materialShininess = " << materialShininess << "\n"; os << " materialSpecular = " << materialSpecular << "\n"; os << " multiSampling = " << multiSampling << "\n"; + os << " perspective = " << perspective << "\n"; os << " shadeModelSmooth = " << shadeModelSmooth << "\n"; + os << " shadow = " << shadow << "\n"; + os << " shadowPolygonOffset = " << shadowPolygonOffset << "\n"; os << " showFaceEdges = " << showFaceEdges << "\n"; os << " showFaces = " << showFaces << "\n"; os << " showMeshEdges = " << showMeshEdges << "\n"; @@ -1285,7 +1334,7 @@ class VSettingsOpenGL // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1375,7 +1424,7 @@ class VSettingsExportImages // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: @@ -1403,6 +1452,7 @@ class VSettingsInteractive // AUTO: float keypressRotationStep; //!< AUTO: rotation increment per keypress in degree (full rotation = 360 degree) float keypressTranslationStep; //!< AUTO: translation increment per keypress relative to window size float mouseMoveRotationFactor; //!< AUTO: rotation increment per 1 pixel mouse movement in degree + bool selectionHighlights; //!< AUTO: True: mouse click highlights item (default: red) bool selectionLeftMouse; //!< AUTO: True: left mouse click on items and show basic information bool selectionRightMouse; //!< AUTO: True: right mouse click on items and show dictionary (read only!) bool useJoystickInput; //!< AUTO: True: read joystick input (use 6-axis joystick with lowest ID found when starting renderer window) and interpret as (x,y,z) position and (rotx, roty, rotz) rotation: as available from 3Dconnexion space mouse and maybe others as well; set to False, if external joystick makes problems ... @@ -1423,6 +1473,7 @@ class VSettingsInteractive // AUTO: keypressRotationStep = 5.f; keypressTranslationStep = 0.1f; mouseMoveRotationFactor = 1.f; + selectionHighlights = true; selectionLeftMouse = true; selectionRightMouse = true; useJoystickInput = true; @@ -1459,6 +1510,7 @@ class VSettingsInteractive // AUTO: os << " keypressRotationStep = " << keypressRotationStep << "\n"; os << " keypressTranslationStep = " << keypressTranslationStep << "\n"; os << " mouseMoveRotationFactor = " << mouseMoveRotationFactor << "\n"; + os << " selectionHighlights = " << selectionHighlights << "\n"; os << " selectionLeftMouse = " << selectionLeftMouse << "\n"; os << " selectionRightMouse = " << selectionRightMouse << "\n"; os << " useJoystickInput = " << useJoystickInput << "\n"; @@ -1481,7 +1533,7 @@ class VSettingsInteractive // AUTO: * * @author AUTO: Gerstmayr Johannes * @date AUTO: 2019-07-01 (generated) -* @date AUTO: 2022-06-16 (last modfied) +* @date AUTO: 2022-06-21 (last modfied) * * @copyright This file is part of Exudyn. Exudyn is free software: you can redistribute it and/or modify it under the terms of the Exudyn license. See "LICENSE.txt" for more details. * @note Bug reports, support and further information: diff --git a/main/src/Autogenerated/versionCpp.cpp b/main/src/Autogenerated/versionCpp.cpp index de944fc3..441a0bdf 100644 --- a/main/src/Autogenerated/versionCpp.cpp +++ b/main/src/Autogenerated/versionCpp.cpp @@ -1,7 +1,7 @@ // AUTO: ++++++++++++++++++++++ // AUTO: version info automatically generated by tracker; generated by Johannes Gerstmayr -// AUTO: last modified = 2022-06-17 +// AUTO: last modified = 2022-06-22 // AUTO: ++++++++++++++++++++++ namespace EXUstd { - const char* exudynVersion = "1.2.134.dev1"; + const char* exudynVersion = "1.3.0"; } diff --git a/main/src/Graphics/GlfwClient.cpp b/main/src/Graphics/GlfwClient.cpp index 4e50cef0..09810e4a 100644 --- a/main/src/Graphics/GlfwClient.cpp +++ b/main/src/Graphics/GlfwClient.cpp @@ -14,6 +14,10 @@ #include "Graphics/GlfwClient.h" #include "Utilities/SlimArray.h" + + +#ifdef USE_GLFW_GRAPHICS + #define GlfwRendererUsePNG //deactivate this flag for compatibility; switches to .TGA image output //needs to be tested!!! @@ -22,16 +26,17 @@ //#endif //we need to exclude Python36 (in fact Ubuntu18.04, where glfw is not available with stb_image_write.h -#if defined(__EXUDYN__LINUX__) && defined(__EXUDYN__PYTHON36) +#if (defined(__EXUDYN__LINUX__) && defined(__EXUDYN__PYTHON36)) #undef GlfwRendererUsePNG #endif +//GlfwRendererUsePNG only makes sense if GLFW_GRAPHICS is available #ifdef GlfwRendererUsePNG #define STB_IMAGE_WRITE_IMPLEMENTATION #include "deps/stb_image_write.h" //for save image as .PNG #endif -#ifdef USE_GLFW_GRAPHICS + using namespace std::string_literals; // enables s-suffix for std::string literals //if this flag is set, the GLFW thread will be detached (which may be advantageous is stoprenderer is not called); otherwise it is a joinable thread @@ -81,7 +86,7 @@ RenderState* GlfwRenderer::state; RenderStateMachine GlfwRenderer::stateMachine; std::thread GlfwRenderer::rendererThread; bool GlfwRenderer::verboseRenderer = false; -Index GlfwRenderer::firstRun = 0; //zoom all in first run +//DELETE: Index GlfwRenderer::firstRun = 0; //zoom all in first run std::atomic_flag GlfwRenderer::renderFunctionRunning = ATOMIC_FLAG_INIT; //!< semaphore to check if Render(...) function is currently running (prevent from calling twice); initialized with clear state std::atomic_flag GlfwRenderer::showMessageSemaphore = ATOMIC_FLAG_INIT; //!< semaphore for ShowMessage @@ -114,6 +119,15 @@ GlfwRenderer::GlfwRenderer() graphicsDataList = nullptr; window = nullptr; + fontScale = 1; //initialized if needed before bitmap initialization + //renderState state cannot be initialized here, because it will be linked later to visualizationSystemContainer + + ResetStateMachine(); +}; + + +void GlfwRenderer::ResetStateMachine() +{ stateMachine.leftMousePressed = false; stateMachine.rightMousePressed = false; stateMachine.shiftPressed = false; @@ -125,14 +139,15 @@ GlfwRenderer::GlfwRenderer() stateMachine.lastMousePressedX = 0; //!< last left mouse button position pressed stateMachine.lastMousePressedY = 0; - //DELETE: stateMachine.selectionMode = false; - //stateMachine.selectionString = ""; - stateMachine.selectionMouseCoordinates = Vector2D({ 0.,0. }); + //initialize highlight item: + stateMachine.highlightIndex = invalidIndex; + stateMachine.highlightType = ItemType::_None; + stateMachine.highlightMbsNumber = 0; + stateMachine.highlightTimeout = 0.; - fontScale = 1; //initialized if needed before bitmap initialization - //renderState state cannot be initialized here, because it will be linked later to visualizationSystemContainer + stateMachine.selectionMouseCoordinates = Vector2D({ 0.,0. }); -}; +} //! add status message, e.g., if button is pressed void GlfwRenderer::ShowMessage(const STDstring& str, Real timeout) @@ -609,10 +624,10 @@ void GlfwRenderer::key_callback(GLFWwindow* window, int key, int scancode, int a //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - if (!hasShift && key == GLFW_KEY_UP && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[1] -= transStep; } - if (!hasShift && key == GLFW_KEY_DOWN && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[1] += transStep; } - if (!hasShift && key == GLFW_KEY_LEFT && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[0] += transStep; } - if (!hasShift && key == GLFW_KEY_RIGHT && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[0] -= transStep; } + if (!hasShift && !hasAlt && key == GLFW_KEY_UP && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[1] -= transStep; } + if (!hasShift && !hasAlt && key == GLFW_KEY_DOWN && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[1] += transStep; } + if (!hasShift && !hasAlt && key == GLFW_KEY_LEFT && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[0] += transStep; } + if (!hasShift && !hasAlt && key == GLFW_KEY_RIGHT && (action == GLFW_PRESS || action == GLFW_REPEAT)) { state->centerPoint[0] -= transStep; } if ((key == GLFW_KEY_KP_SUBTRACT || key == GLFW_KEY_COMMA) && (action == GLFW_PRESS || action == GLFW_REPEAT)) { @@ -631,19 +646,27 @@ void GlfwRenderer::key_callback(GLFWwindow* window, int key, int scancode, int a else { state->zoom /= zoomStep;; } } - if (key == GLFW_KEY_A && action == GLFW_PRESS) { ZoomAll(); UpdateGraphicsDataNow(); } + if (key == GLFW_KEY_A && action == GLFW_PRESS) + { + ZoomAll(); + } + //if (key == GLFW_KEY_O && action == GLFW_PRESS) + //{ + // const Float16& A = state->modelRotation; + // Matrix3DF rotMatrix(3, 3, { A[0], A[1], A[2], A[4], A[5], A[6], A[8], A[9], A[10] }); + + // //check which offset or rotation is needed here! + // *** + // state->rotationCenterPoint = rotMatrix.GetTransposed()*state->centerPoint; + // pout << "rot center point=" << state->rotationCenterPoint << "\n"; + //} } //EXUstd::ReleaseSemaphore(graphicsUpdateAtomicFlag); } -void GlfwRenderer::ZoomAll() +void GlfwRenderer::ComputeMaxSceneSize(float& maxSceneSize, Float3& center) { - //pout << "zoom all\n"; - //pout << "graphicsDataList=" << graphicsDataList << "\n"; //max scene size from current line data: - //Float3 pmax({ -1e30f,-1e30f,-1e30f }); - //Float3 pmin({ 1e30f,1e30f,1e30f }); - Float3 pmax({ -1e30f,-1e30f,-1e30f }); Float3 pmin({ 1e30f,1e30f,1e30f }); @@ -698,31 +721,31 @@ void GlfwRenderer::ZoomAll() } } - Float3 center = 0.5f*(pmin + pmax); + center = 0.5f*(pmin + pmax); - float maxSceneSize = (pmax - pmin).GetL2Norm(); + maxSceneSize = (pmax - pmin).GetL2Norm(); if (maxSceneSize < visSettings->general.minSceneSize) { maxSceneSize = visSettings->general.minSceneSize; } if (graphicsDataList->NumberOfItems() == 0 || ((*graphicsDataList)[0]->glCirclesXY.NumberOfItems() == 0 && (*graphicsDataList)[0]->glLines.NumberOfItems() == 0 && (*graphicsDataList)[0]->glSpheres.NumberOfItems() == 0 && (*graphicsDataList)[0]->glTexts.NumberOfItems() == 0 - && (*graphicsDataList)[0]->glTriangles.NumberOfItems() == 0)) + && (*graphicsDataList)[0]->glTriangles.NumberOfItems() == 0)) { maxSceneSize = 1; center = Float3({ 0,0,0 }); } + } +} - //rendererOut << "Zoom all\n"; - //rendererOut << "maxScenesize=" << maxSceneSize << "\n"; - //rendererOut << "center=" << center << "\n"; +//! at beginning with autofitScene and when manually requested +void GlfwRenderer::ZoomAll(bool updateGraphicsData, bool computeMaxScene, bool render) +{ + if (updateGraphicsData) { UpdateGraphicsDataNow(); } + if (computeMaxScene) { ComputeMaxSceneSize(state->maxSceneSize, state->centerPoint); } - state->zoom = 0.4f*maxSceneSize; - state->centerPoint = center; - //state->zoom = 0.5f*state->maxSceneSize; - //state->centerPoint = state->sceneCenterPoint; //computed in VisualizationSystem::UpdateMaximumSceneCoordinates + state->zoom = 0.4f*state->maxSceneSize; - UpdateGraphicsDataNow(); //remove from here; just put here for testing - } + if (render) { Render(window); } } void GlfwRenderer::scroll_callback(GLFWwindow* window, double xoffset, double yoffset) @@ -934,12 +957,12 @@ void GlfwRenderer::cursor_position_callback(GLFWwindow* window, double xpos, dou } } -//! return true, if joystick available and updated values are available; if joystickNumber==-1, chose a joystick; -//! if joystickNumber!=-1, it uses the fixed joystick until end of Renderer +//! return true, if joystick available and updated values are available; if joystickNumber==invalidIndex, chose a joystick; +//! if joystickNumber!=invalidIndex, it uses the fixed joystick until end of Renderer bool GlfwRenderer::GetJoystickValues(Vector3D& position, Vector3D& rotation, Index& joystickNumber) { bool initFirst = false; //if initialized first, also reset stateMachine - if (joystickNumber == -1) + if (joystickNumber == invalidIndex) { //check if joystick available for (Index i = 0; i <= GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1; i++) @@ -989,9 +1012,6 @@ void GlfwRenderer::ProcessJoystick() stateMachine.mode == RendererMode::_None && //only if no other move/zoom action ongoing! GetJoystickValues(state->joystickPosition, state->joystickRotation, state->joystickAvailable)) { - //for debugging ... - //ShowMessage("joystick =" + EXUstd::ToString(state->joystickPosition) + EXUstd::ToString(state->joystickRotation)); - Vector3D diffPos = state->joystickPosition - stateMachine.storedJoystickPosition; Vector3D diffRot = state->joystickRotation - stateMachine.storedJoystickRotation; stateMachine.storedJoystickPosition = state->joystickPosition; @@ -1014,14 +1034,6 @@ void GlfwRenderer::ProcessJoystick() if (!(diffRot == 0.)) { diffRot *= visSettings->interactive.joystickScaleRotation; - //local rotations: - //glMatrixMode(GL_MODELVIEW); - ////glLoadIdentity(); //start with identity - //glLoadMatrixf(state->modelRotation.GetDataPointer()); //load previous rotation - //glRotatef((float)diffRot[0], 1.f, 0.f, 0.f); //apply "incremental" rotation around x - //glRotatef((float)diffRot[1], 0.f, 1.f, 0.f); //apply "incremental" rotation around y - //glRotatef(-(float)diffRot[2], 0.f, 0.f, 1.f); //apply "incremental" rotation around z - //glGetFloatv(GL_MODELVIEW_MATRIX, state->modelRotation.GetDataPointer()); //store rotation in modelRotation, applied in model rendering glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //start with identity @@ -1058,15 +1070,16 @@ bool GlfwRenderer::MouseSelect(GLFWwindow* window, Index mouseX, Index mouseY, I (Index)stateMachine.selectionMouseCoordinates[0], (Index)stateMachine.selectionMouseCoordinates[1], itemID); - //DELETE: stateMachine.selectionMode = false; - Index itemIndex; - ItemType itemType; - Index mbsNumber; - ItemID2IndexType(itemID, itemIndex, itemType, mbsNumber); + + const Real timeOutHighlightItem = 0.5; //just short to exactly see object + ItemID2IndexType(itemID, stateMachine.highlightIndex, stateMachine.highlightType, stateMachine.highlightMbsNumber); + //PrintDelayed("itemID=" + EXUstd::ToString(itemID)); - if (itemType != ItemType::_None && itemIndex != -1) + if (stateMachine.highlightType != ItemType::_None && stateMachine.highlightIndex != invalidIndex) { + stateMachine.highlightTimeout = EXUstd::GetTimeInSeconds() + timeOutHighlightItem; //5 seconds timeout + STDstring itemTypeName; STDstring itemName; //STDstring itemInfo; @@ -1076,15 +1089,13 @@ bool GlfwRenderer::MouseSelect(GLFWwindow* window, Index mouseX, Index mouseY, I { ShowMessage("Selected item: " + itemTypeName + //"type = " + EXUstd::ToString(itemType) + - ", index = " + EXUstd::ToString(itemIndex) + " (" + itemName + ")", 0); + ", index = " + EXUstd::ToString(stateMachine.highlightIndex) + " (" + itemName + ")", 0); } - //UpdateGraphicsDataNow(); return true; } else { ShowMessage("no item selected", 2); - //DELETE: stateMachine.selectionMode = false; return false; } } @@ -1094,7 +1105,6 @@ void GlfwRenderer::MouseSelectOpenGL(GLFWwindow* window, Index mouseX, Index mou { //++++++++++++++++++++++++++++++++++++++++ //put into separate function, for Render(...) - float ratio; int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -1103,16 +1113,11 @@ void GlfwRenderer::MouseSelectOpenGL(GLFWwindow* window, Index mouseX, Index mou state->currentWindowSize[0] = width; state->currentWindowSize[1] = height; - ratio = (float)width; - if (height != 0) - { - ratio = width / (float)height; - } + float ratio = (float)width; + if (height != 0) { ratio = width / (float)height; } - GLfloat zoom = state->zoom; //++++++++++++++++++++++++++++++++++++++++ - const Index selectBufferSize = 10000; //size for number of objects picked at same time GLuint selectBuffer[selectBufferSize]; glSelectBuffer(selectBufferSize, selectBuffer); @@ -1123,16 +1128,6 @@ void GlfwRenderer::MouseSelectOpenGL(GLFWwindow* window, Index mouseX, Index mou //rendererOut << "viewport=" << viewport[0] << ", " << viewport[1] << ", " << viewport[2] << ", " << viewport[3] << "\n"; //rendererOut << "mouse=" << mouseX << ", " << mouseY << "\n"; - ////from meshDoc: - //glMatrixMode(GL_PROJECTION); - //glPushMatrix(); - - //GLdouble projmat[16]; - //glGetDoublev(GL_PROJECTION_MATRIX, projmat); - - //glLoadIdentity(); - - float backgroundColor = 0.f; glClearColor(backgroundColor, backgroundColor, backgroundColor, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -1147,9 +1142,9 @@ void GlfwRenderer::MouseSelectOpenGL(GLFWwindow* window, Index mouseX, Index mou SetViewOnMouseCursor(mouseX, viewport[3] - mouseY, selectArea*ratio, selectArea, viewport); //add ratio to make area non-distorted?q //++++++++++++++++++++++++++++++++++++++++ - //use function for that part: - GLdouble zFactor = 100.; //original:100 - glOrtho(-ratio * zoom, ratio*zoom, -zoom, zoom, -zFactor * 2.*state->maxSceneSize, zFactor * 2.*state->maxSceneSize); //https: //www.khronos.org/opengl/wiki/Viewing_and_Transformations#How_do_I_implement_a_zoom_operation.3F + float zoom; + GLdouble zFactor; + SetProjection(width, height, ratio, zoom, zFactor); //set zoom, perspective, ...; may not work for larger perspective glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -1227,7 +1222,13 @@ bool GlfwRenderer::SetupRenderer(bool verbose) { PySetRendererCallbackLock(false); //reset callback lock if still set from earlier run (for safety ...) - basicVisualizationSystemContainer->UpdateMaximumSceneCoordinates(); //this is done to make OpenGL zoom and maxSceneCoordinates work + basicVisualizationSystemContainer->InitializeView(); //this is done to make OpenGL zoom and maxSceneCoordinates work + basicVisualizationSystemContainer->SetComputeMaxSceneRequest(true); //computes maxSceneCoordinates for perspective and shadow + if (visSettings->general.autoFitScene) + { + basicVisualizationSystemContainer->SetZoomAllRequest(true); + //pout << "set zoom all\n"; + } basicVisualizationSystemContainer->ForceQuitSimulation(false); //reset flag if set from earlier simulations rendererError = 0; @@ -1467,7 +1468,8 @@ void GlfwRenderer::InitCreateWindow() //+++++++++++++++++++++++++++++++++ //joystick - state->joystickAvailable = -1; //this causes to search for new joystick and, if fourn, initialize stateMachine! + state->joystickAvailable = invalidIndex; //this causes to search for new joystick and, if fourn, initialize stateMachine! + ResetStateMachine(); //+++++++++++++++++ //initialize opengl @@ -1512,7 +1514,7 @@ void GlfwRenderer::InitCreateWindow() //+++++++++++++++++++++++++++++++++ //do this just before RunLoop, all initialization finished ... - firstRun = 0; //zoom all on startup of window + //DELETE: firstRun = 0; //zoom all on startup of window rendererActive = true; //this is still threadsafe, because main thread waits for this signal! //+++++++++++++++++++++++++++++++++ @@ -1591,7 +1593,19 @@ void GlfwRenderer::DoRendererTasks() if (useMultiThreadedRendering || (time >= lastGraphicsUpdate + updateInterval) || GetCallBackSignal()) { basicVisualizationSystemContainer->UpdateGraphicsData(); - if (basicVisualizationSystemContainer->GetAndResetZoomAllRequest()) { ZoomAll(); } + bool maxSceneComputed = false; + if (basicVisualizationSystemContainer->GetComputeMaxSceneRequest()) + { + ComputeMaxSceneSize(state->maxSceneSize, state->centerPoint); + maxSceneComputed = true; + basicVisualizationSystemContainer->SetComputeMaxSceneRequest(false); + //pout << "maxSceneSize=" << state->maxSceneSize << ", center=" << state->centerPoint << "\n"; + //pout << "ComputeMaxSceneSize\n"; + } + if (basicVisualizationSystemContainer->GetAndResetZoomAllRequest()) { + ZoomAll(false, !maxSceneComputed, false); + //pout << "Zoom all\n"; + } Render(window); SaveImage(); //in case of flag, save frame to image file lastGraphicsUpdate = time; @@ -1668,13 +1682,40 @@ void GlfwRenderer::DoRendererIdleTasks(Real waitSeconds) } } +//load GL_PROJECTION and set according to zoom, perspective, etc. +void GlfwRenderer::SetProjection(int width, int height, float ratio, float& zoom, GLdouble& zFactor) +{ + zoom = state->zoom; + zFactor = 100.; //z-factor to avoid clipping; original:100 + + if (visSettings->openGL.perspective <= 0) + { + glOrtho(-ratio * zoom, ratio*zoom, -zoom, zoom, -zFactor * 2.*state->maxSceneSize, zFactor * 2.*state->maxSceneSize); //https: //www.khronos.org/opengl/wiki/Viewing_and_Transformations#How_do_I_implement_a_zoom_operation.3F + //void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble nearVal,GLdouble farVal); + } + else + { + //visSettings->openGL.perspective + float fact = 1.f / (float)visSettings->openGL.perspective; + float factZoom = 0.5f; //correction, to show same zoom level as orthographic projection + + float zNear = state->maxSceneSize*fact; + float zFar = state->maxSceneSize * (4.f*fact + 2.f); + float right = ratio * zoom*factZoom; + float left = -right; + float top = zoom * factZoom; + float bottom = -zoom * factZoom; + glFrustum(left, right, bottom, top, zNear, zFar); + glTranslatef(0.f, 0.f, -2 * fact * state->maxSceneSize); + } +} + void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, because of glfwSetWindowRefreshCallback { if (PyGetRendererCallbackLock()) { return; } EXUstd::WaitAndLockSemaphore(renderFunctionRunning); //lock Render(...) function, no second call possible //std::cout << "start renderer\n"; - float ratio; int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -1683,13 +1724,6 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, state->currentWindowSize[0] = width; state->currentWindowSize[1] = height; - ratio = (float)width; - if (height != 0) - { - ratio = width / (float)height; - } - - GLfloat zoom = state->zoom; //determine the windows scale; TODO: add callback to redraw if monitor is changed: glfwSetWindowContentScaleCallback(...) //float xWindowScale, yWindowScale; @@ -1714,13 +1748,15 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, glClearColor(bg[0], bg[1], bg[2], bg[3]); //(float red, float green, float blue, float alpha); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - GLdouble zFactor = 100.; //original:100 - glOrtho(-ratio * zoom, ratio*zoom, -zoom, zoom, -zFactor*2.*state->maxSceneSize, zFactor * 2.*state->maxSceneSize); //https: //www.khronos.org/opengl/wiki/Viewing_and_Transformations#How_do_I_implement_a_zoom_operation.3F - //original (flipped?): - //glOrtho(-ratio * zoom, ratio*zoom, -1.f*zoom, 1.f*zoom, zFactor*2.*state->maxSceneSize, -zFactor * 2.*state->maxSceneSize); //https: //www.khronos.org/opengl/wiki/Viewing_and_Transformations#How_do_I_implement_a_zoom_operation.3F + + float ratio = (float)width; + if (height != 0) { ratio = width / (float)height; } + float zoom; + GLdouble zFactor; + SetProjection(width, height, ratio, zoom, zFactor); //set zoom, perspective, ... + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -1747,18 +1783,42 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, //put here, will be fixed light seen from camera: SetGLLights(); //moved here 2020-12-05; light should now be rotation independent! - glTranslated(-state->centerPoint[0], -state->centerPoint[1], 0.f); + //++++++++++++++++++++++++++++++++++++++++++++++++++++ + //model rotation and translation, include rotation center point + const Float16& A = state->modelRotation; + Matrix3DF rotMatrix(3, 3, { A[0], A[1], A[2], A[4], A[5], A[6], A[8], A[9], A[10] }); + + glTranslatef(-state->centerPoint[0], -state->centerPoint[1], 0.f); + + //Float3 rot2 = state->rotationCenterPoint; + //glTranslatef(rot2[0], rot2[1], rot2[2]); glMultMatrixf(state->modelRotation.GetDataPointer()); + + ////rot2 = rotMatrix.GetTransposed() * (-state->rotationCenterPoint); //A.T*rotationCenterPoint + //rot2 = (-state->rotationCenterPoint); //A.T*rotationCenterPoint + //glTranslatef(rot2[0], rot2[1], rot2[2]); + //++++++++++++++++++++++++++++++++++++++++++++++++++++ + + //glRotatef(state->rotations[2], 0.f, 0.f, 1.f);//((float)glfwGetTime() * 50.f, 0.f, 0.f, 1.f); //glRotatef(state->rotations[1], 0.f, 1.f, 0.f); //glRotatef(state->rotations[0], 1.f, 0.f, 0.f); //put here, will rotate with model-view: - //SetGLLights(); //moved here 2020-12-05; light should now be rotation independent! + //SetGLLights(); RenderGraphicsData(); + + if (visSettings->openGL.perspective != 0) + { + //for texts, axes, etc.: draw without perspective + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-ratio * zoom, ratio*zoom, -zoom, zoom, -zFactor * 2.*state->maxSceneSize, zFactor * 2.*state->maxSceneSize); //https: //www.khronos.org/opengl/wiki/Viewing_and_Transformations#How_do_I_implement_a_zoom_operation.3F + } + //glPushMatrix(); //store current matrix //glPopMatrix(); //restore matrix const int textIndentPixels = 10; @@ -1948,14 +2008,6 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, p0 += Float3({ 0.f,-sizeY,0.f }); } - // glBegin(GL_TRIANGLES); - // glColor3f(1.f, 0.f, 0.f); - // glVertex3f(-0.6f+i, -0.4f+j, 0.f); - // glColor3f(0.f, 1.f, 0.f); - // glVertex3f(0.6f+i, -0.4f+j, 0.f); - // glColor3f(0.f, 0.f, 1.f); - // glVertex3f(0.f+i, 0.6f+j, 0.f); - // glEnd(); glDepthMask(GL_TRUE); } @@ -1981,9 +2033,6 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - //float factor = -0.35f*zoom * 2.5f; - //glOrtho(0.0f, ratio, 1, 0.0f, 0.0f, 1.0f); - //float factor = -0.35f; Float2 pPix = PixelToVertexCoordinates(10 + visSettings->general.coordinateSystemSize*fontSize, 10 + (visSettings->general.coordinateSystemSize+0.f)*fontSize); //+1.f because of possible status line at bottom @@ -2046,12 +2095,11 @@ void GlfwRenderer::Render(GLFWwindow* window) //GLFWwindow* needed in argument, glfwSwapBuffers(window); - //rendererOut << "Render ready\n"; - - firstRun++; - //if (firstRun == 10) { ZoomAll(); } + //DELETE: + //firstRun++; + ////if (firstRun == 10) { ZoomAll(); } - if ((firstRun * visSettings->general.graphicsUpdateInterval) < 1. && visSettings->general.autoFitScene) { ZoomAll(); } + //if ((firstRun * visSettings->general.graphicsUpdateInterval) < 1. && visSettings->general.autoFitScene) { ZoomAll(); } //std::cout << " finish renderer\n"; @@ -2208,10 +2256,10 @@ void GlfwRenderer::RenderGraphicsData(bool selectionMode) { if (graphicsDataList) { - Index lastItemID = -1; + Index lastItemID = invalidIndex; if (selectionMode) { - glLoadName(-1); //to have some name in + glLoadName(invalidIndex); //to have some name in it } //check if item shall be highlighted: bool highlight = false; @@ -2220,10 +2268,26 @@ void GlfwRenderer::RenderGraphicsData(bool selectionMode) Float4 highlightColor2 = visSettings->interactive.highlightColor; //for text and lines Float4 otherColor2 = visSettings->interactive.highlightOtherColor; //for text and lines - + //Index highlightIndex; + //ItemType highlightType; + //Index highlightMbsNumber; Index highlightIndex = visSettings->interactive.highlightItemIndex; ItemType highlightType = visSettings->interactive.highlightItemType; Index highlightMbsNumber = visSettings->interactive.highlightMbsNumber; + if (visSettings->interactive.selectionHighlights && stateMachine.highlightIndex != invalidIndex) + { + //if selected with mouse, temporarily use this: + if (stateMachine.highlightTimeout != 0. && stateMachine.highlightTimeout < EXUstd::GetTimeInSeconds()) + { + stateMachine.highlightIndex = invalidIndex; //from now on, no further highlighting + } + else + { + highlightIndex = stateMachine.highlightIndex; + highlightType = stateMachine.highlightType; + highlightMbsNumber = stateMachine.highlightMbsNumber; + } + } Index highlightID = Index2ItemID(highlightIndex, highlightType, highlightMbsNumber); if (highlightIndex >= 0 && highlightType != ItemType::_None) @@ -2494,6 +2558,10 @@ void GlfwRenderer::RenderGraphicsData(bool selectionMode) glEnd(); } } + if (!selectionMode && visSettings->openGL.shadow != 0) + { + DrawTrianglesWithShadow(data); + } } else //for global transparency of faces; slower { @@ -2566,11 +2634,140 @@ void GlfwRenderer::RenderGraphicsData(bool selectionMode) } //for (auto data : *graphicsDataList) if (selectionMode) { - glLoadName(-1); //to have some name in + glLoadName(invalidIndex); //to have some name in } } //if graphicsDataList } +//draw stenciled shadow volume +//following concepts of https://github.com/joshb/shadowvolumes +void RenderTriangleShadowVolume(const GLTriangle& trig, const Float3& lightPos, float maxDist, float shadow) +{ + //glColor4f(0.6f,0.3f,0.3f,1); + bool computeNormals = false; + //glColor4f(0.f, 0.f, 0.f, shadow);//shadow + + //check if triangle normal is looking in direction of light (otherwise no shadow is produced + if (EXUmath::ComputeTriangleNormal(trig.points[0], trig.points[1], trig.points[2]) * (lightPos - trig.points[0]) > 0) + { + if (computeNormals) { glNormal3fv(EXUmath::ComputeTriangleNormal(trig.points[0], trig.points[1], trig.points[2]).GetDataPointer()); } + glBegin(GL_TRIANGLES); + for (Index i = 0; i < 3; i++) + { + glVertex3fv(trig.points[i].GetDataPointer()); + } + std::array< Float3, 3> farPoints; + + if (computeNormals) { glNormal3fv(EXUmath::ComputeTriangleNormal(trig.points[2], trig.points[1], trig.points[0]).GetDataPointer()); } + for (Index i = 2; i >= 0; i--) + { + Float3 vecDist = trig.points[i] - lightPos; + float dist = vecDist.SumAbs()*0.577f; //cheaper than norm, but needs safety factor sqrt(3) + //float dist = vecDist.GetL2Norm(); //SumAbs()*0.577 would be cheaper and also on safe side + if (dist != 0) + { + vecDist *= maxDist / dist; //scale up to maximum distance in scene, will cover all objects + } + + farPoints[i] = trig.points[i] + vecDist; + glVertex3fv(farPoints[i].GetDataPointer()); + } + glEnd(); + + glBegin(GL_QUADS); + for (Index i = 0; i < 3; i++) + { + Index iNext = (i + 1) % 3; + if (computeNormals) { glNormal3fv(EXUmath::ComputeTriangleNormal(trig.points[i], farPoints[i], farPoints[iNext]).GetDataPointer()); } + glVertex3fv(trig.points[i].GetDataPointer()); + glVertex3fv(farPoints[i].GetDataPointer()); + glVertex3fv(farPoints[iNext].GetDataPointer()); + glVertex3fv(trig.points[iNext].GetDataPointer()); + } + glEnd(); + } + +} + +//draw full plane over screen, containing shadow mask +void DrawShadowPlane(float shadow) +{ + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, 1, 1, 0, 0, 1); + glDisable(GL_DEPTH_TEST); + + glColor4f(0.0f, 0.0f, 0.0f, shadow); + glBegin(GL_QUADS); + glVertex2i(0, 0); + glVertex2i(0, 1); + glVertex2i(1, 1); + glVertex2i(1, 0); + glEnd(); + + glEnable(GL_DEPTH_TEST); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +void GlfwRenderer::DrawTrianglesWithShadow(GraphicsData* data) +{ + const Float4& lp = visSettings->openGL.light0position; + Float3 lightPos({ lp[0], lp[1], lp[2] }); + float maxDist = state->maxSceneSize*1.5f; + float shadow = EXUstd::Minimum(visSettings->openGL.shadow, 1.f); + + //add shadow now: + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); + glEnable(GL_CULL_FACE); + glEnable(GL_STENCIL_TEST); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(0.0f, visSettings->openGL.shadowPolygonOffset * state->maxSceneSize); //original: 100.0f, may be too big + + glCullFace(GL_FRONT); + glStencilFunc(GL_ALWAYS, 0x0, 0xff); + glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); + for (const GLTriangle& trig : data->glTriangles) + { //draw faces + if ((visSettings->openGL.showFaces && !trig.isFiniteElement) + || (visSettings->openGL.showMeshFaces && trig.isFiniteElement)) + { + RenderTriangleShadowVolume(trig, lightPos, maxDist, shadow); + } + } + glCullFace(GL_BACK); + glStencilFunc(GL_ALWAYS, 0x0, 0xff); + glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); + for (const GLTriangle& trig : data->glTriangles) + { //draw faces + if ((visSettings->openGL.showFaces && !trig.isFiniteElement) + || (visSettings->openGL.showMeshFaces && trig.isFiniteElement)) + { + RenderTriangleShadowVolume(trig, lightPos, maxDist, shadow); + } + } + + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_CULL_FACE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + + glStencilFunc(GL_NOTEQUAL, 0x0, 0xff); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + + DrawShadowPlane(shadow); + + glDisable(GL_STENCIL_TEST); + + +} #endif //USE_GLFW_GRAPHICS diff --git a/main/src/Graphics/GlfwClient.h b/main/src/Graphics/GlfwClient.h index d9c36814..a0f5c338 100644 --- a/main/src/Graphics/GlfwClient.h +++ b/main/src/Graphics/GlfwClient.h @@ -82,10 +82,12 @@ class RenderStateMachine //++++++++++++++++++++++++++++++++++++ //selection: - //DELETE: selectionMode; //!< true, if in selection mode - Vector2D selectionMouseCoordinates; //!mouse coordinates used for selection - //std::string selectionString; //!< string about object to be shown on screen - + Vector2D selectionMouseCoordinates; //!< mouse coordinates used for selection + Index highlightIndex; //!< item index of selected item (with mouse click) + ItemType highlightType; //!< item type of selected item + Index highlightMbsNumber; //!< mbs number of selected item + Real highlightTimeout; //!< time at which highlighted item shall be removed, using EXUstd::GetTimeInSeconds(); 0, if no timeout + std::string rendererMessage; //!< rendererMessage to be shown in status line Real renderMessageTimeout; //!< time at which message shall be removed, using EXUstd::GetTimeInSeconds(); 0, if no timeout @@ -110,7 +112,7 @@ class GlfwRenderer static std::thread rendererThread; //!< std::thread variable for rendererThread static Index rendererError; //!< 0 ... no error, 1 ... glfwInit() failed, 2 ... glfwCreateWindow failed, 3 ... other error static bool verboseRenderer; //!< initialized in SetupRenderer(bool verbose): output helpful information - static Index firstRun; //zoom all in first run + //static Index firstRun; //zoom all in first run static std::atomic_flag renderFunctionRunning; //!< semaphore to check if Render(...) function is currently running (prevent from calling twice) static std::atomic_flag showMessageSemaphore; //!< semaphore to prevent calling ShowMessage twice @@ -134,6 +136,7 @@ class GlfwRenderer static GLuint spheresListBase; //!< starting index for GLlists for spheres static constexpr Index maxSpheresLists = 8; //!< max. number of GLlists for spheres (with resolution 2,4,8,16, etc. + static constexpr Index invalidIndex = -1; //!< for some state machine variables (itemIndex, joystick number, ...) //+++++++++++++++++++++++++++++++++++++++++ //link to GraphicsData and Settings: static ResizableArray* graphicsDataList; //!< link to graphics data; only works for one MainSystem, but could also be realized for several systems @@ -159,6 +162,9 @@ class GlfwRenderer //! return renderState object static RenderState GetRenderState() { return *state; } + //! reset some state machines, e.g., left mouse click, item select, etc. + static void ResetStateMachine(); + static bool WindowIsInitialized() { if (window && rendererActive) { return true; } @@ -183,7 +189,7 @@ class GlfwRenderer state->mouseLeftPressed = false; state->mouseRightPressed = false; state->mouseMiddlePressed = false; - state->joystickAvailable = -1; + state->joystickAvailable = invalidIndex; return true; } else { return false; } @@ -287,8 +293,8 @@ class GlfwRenderer static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos); static void window_close_callback(GLFWwindow* window); - //! return true, if joystick available and updated values are available; if joystickNumber==-1, chose a joystick; - //! if joystickNumber!=-1, it uses the fixed joystick until end of Renderer + //! return true, if joystick available and updated values are available; if joystickNumber==invalidIndex, chose a joystick; + //! if joystickNumber!=invalidIndex, it uses the fixed joystick until end of Renderer static bool GetJoystickValues(Vector3D& position, Vector3D& rotation, Index& joystickNumber); //! read joystick values; if changed, send refresh signal for graphics @@ -322,6 +328,8 @@ class GlfwRenderer //! Render function called for every update of OpenGl window static void Render(GLFWwindow* window); //GLFWwindow* needed in argument, because of glfwSetWindowRefreshCallback + static void SetProjection(int width, int height, float ratio, float& zoom, GLdouble& zFactor); //load GL_PROJECTION and set according to zoom, perspective, etc. + //! check if frame shall be grabed and saved to file using visualization options static void SaveImage(); @@ -331,8 +339,14 @@ class GlfwRenderer //! Render particulary the graphics data of multibody system; selectionMode==true adds names static void RenderGraphicsData(bool selectionMode = false); // fontScale now stored in GLFWRenderer: float fontScale); + //! Render triangles with stencil shadow method (slow, but accurate and should be sufficient for some animations) + static void DrawTrianglesWithShadow(GraphicsData* data); + + //! compute maxSceneSize and center from graphicsData + static void ComputeMaxSceneSize(float& maxSceneSize, Float3& center); + //! Zoom all graphics objects (for current configuration) - static void ZoomAll(); + static void ZoomAll(bool updateGraphicsData=true, bool computeMaxScene=true, bool render=true); //! Set all light functions for openGL static void SetGLLights(); diff --git a/main/src/Graphics/PostProcessData.h b/main/src/Graphics/PostProcessData.h index 74316c7b..a34ced82 100644 --- a/main/src/Graphics/PostProcessData.h +++ b/main/src/Graphics/PostProcessData.h @@ -45,7 +45,8 @@ class PostProcessData bool forceQuitSimulation; //!< flag is set if user closes simulation window (but not if Escape pressed) bool simulationPaused; //!< true: simulation sends renderer or GUI that simulation is paused, waiting for user-input (SPACE) Real visualizationTime; //!< this value is set as soon as the computation date is generated from visualization; needed to synchronize text message and visualization state - + bool systemHasChanged; //!< systemHasChanged is used to signal GLFWclient to compute new maxSceneSize and center + VisualizationSystem* visualizationSystem; //!< this backlink ist used for: user functions, WaitForUserToContinue and for MainSystem backlink (but use rarely!!!) bool requestUserFunctionDrawing; //!< if this flag is set, user functions request drawing update from computation thread std::atomic_flag requestUserFunctionDrawingAtomicFlag; //!< flag for user function drawing in python @@ -67,6 +68,7 @@ class PostProcessData forceQuitSimulation = false; simulationPaused = false; visualizationTime = 0; + systemHasChanged = true; // used to compute maxSceneSize at beginning visualizationStateUpdateAvailable = false; requestUserFunctionDrawing = false; diff --git a/main/src/Graphics/VisualizationSystem.cpp b/main/src/Graphics/VisualizationSystem.cpp index 5b0e1e59..41dd6724 100644 --- a/main/src/Graphics/VisualizationSystem.cpp +++ b/main/src/Graphics/VisualizationSystem.cpp @@ -97,6 +97,13 @@ void VisualizationSystem::UpdateGraphicsData(VisualizationSystemContainer& visua systemData->GetCData().visualizationState = postProcessData->GetVisualizationStateUpdate(); postProcessData->SetVisualizationStateUpdateAvailable(false); } + + if (GetSystemHasChanged()) + { + visualizationSystemContainer.SetComputeMaxSceneRequest(true); + SetSystemHasChanged(false); + } + EXUstd::ReleaseSemaphore(postProcessData->accessState); //now visualizationStateUpdate can be written again in main thread try diff --git a/main/src/Graphics/VisualizationSystem.h b/main/src/Graphics/VisualizationSystem.h index 93a6dead..f7724c38 100644 --- a/main/src/Graphics/VisualizationSystem.h +++ b/main/src/Graphics/VisualizationSystem.h @@ -60,6 +60,10 @@ class VisualizationSystem //: public VisualizationSystemBase public: virtual ~VisualizationSystem() {} //added for correct deletion of derived classes + //! systemHasChanged is used to signal GLFWclient to compute new maxSceneSize and center + void SetSystemHasChanged(bool flag) { postProcessData->systemHasChanged = flag; } + bool GetSystemHasChanged() { return postProcessData->systemHasChanged; } + GraphicsData& GetGraphicsData() { return graphicsData; } const GraphicsData& GetGraphicsData() const { return graphicsData; } @@ -107,7 +111,7 @@ class VisualizationSystem //: public VisualizationSystemBase virtual std::string GetComputationMessage(bool solverInformation = true, bool solutionInformation = true, bool solverTime = true); //! if the system has changed or loaded, compute maximum box of all items and reset scene to the maximum box - //virtual void UpdateMaximumSceneCoordinates(); + //virtual void InitializeView(); virtual void Print(std::ostream& os) const { diff --git a/main/src/Graphics/VisualizationSystemContainer.cpp b/main/src/Graphics/VisualizationSystemContainer.cpp index 7139e7ab..04a761bd 100644 --- a/main/src/Graphics/VisualizationSystemContainer.cpp +++ b/main/src/Graphics/VisualizationSystemContainer.cpp @@ -63,13 +63,13 @@ bool VisualizationSystemContainer::DetachFromRenderEngine(VisualizationSystemCon //! OpenGL renderer sends message that graphics shall be updated ==> update graphics data void VisualizationSystemContainer::UpdateGraphicsData() { - if (zoomAllRequest) - { - zoomAllRequest = false; //this is not fully thread safe, but should not happen very often ==> user needs to zoom manually then ... - //pout << "zoomAllrequest1\n"; - UpdateMaximumSceneCoordinates(); - //pout << "zoomAllrequest2\n"; - } + //this is now done in GLFWclient for zoom all, InitializeView done + //if (zoomAllRequest) + //{ + // zoomAllRequest = false; //this is not fully thread safe, but should not happen very often ==> user needs to zoom manually then ... + + // InitializeView(); + //} if (updateGraphicsDataNow) { updateGraphicsDataNowInternal = true; updateGraphicsDataNow = false; } //enables immediate new set of updateGraphicsDataNow if (saveImage) { saveImageOpenGL = true; } //as graphics are updated now, the saveImageOpenGL flag can be set @@ -211,13 +211,14 @@ bool VisualizationSystemContainer::WaitForRenderEngineStopFlag() } //! if the system has changed or loaded, compute maximum box of all items and reset scene to the maximum box -void VisualizationSystemContainer::UpdateMaximumSceneCoordinates() +void VisualizationSystemContainer::InitializeView() { //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - renderState.centerPoint = settings.openGL.initialCenterPoint; //this is the initial centerPoint; hereafter it can be changed! - //renderState.sceneCenterPoint = settings.openGL.initialCenterPoint; //this is the initial centerPoint; hereafter it can be changed! renderState.zoom = settings.openGL.initialZoom; renderState.maxSceneSize = settings.openGL.initialMaxSceneSize; + renderState.centerPoint = settings.openGL.initialCenterPoint; //this is the initial centerPoint; hereafter it can be changed! + //renderState.rotationCenterPoint.SetAll(0); + renderState.currentWindowSize = settings.window.renderWindowSize; if (renderState.currentWindowSize[0] < 1) { renderState.currentWindowSize[0] = 1; } //avoid division by zero if (renderState.currentWindowSize[1] < 1) { renderState.currentWindowSize[1] = 1; } //avoid division by zero @@ -237,58 +238,59 @@ void VisualizationSystemContainer::UpdateMaximumSceneCoordinates() //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - if (settings.general.autoFitScene) - { - //for now, use nodal reference coordinates to estimate the maximum zoom level - Vector3D pmax0({ -1e30,-1e30,-1e30 }); - Vector3D pmin0({ 1e30,1e30,1e30 }); - Vector3D pmax = pmax0; - Vector3D pmin = pmin0; - for (auto visSystem : visualizationSystems) - { - //! @todo extend VisualizationSystemContainer::UpdateMaximumSceneCoordinates for objects, markers and loads; maybe better to first draw all and zoom to full region? - for (auto item : visSystem->systemData->GetCNodes()) - { - if ((Index)item->GetNodeGroup() & (Index)CNodeGroup::ODE2variables) - { - //LinkedDataVector pref = item->GetReferenceCoordinateVector(); - Vector3D pref = ((CNodeODE2*)item)->GetPosition(ConfigurationType::Reference); - - pmax[0] = EXUstd::Maximum(pref[0], pmax[0]); - pmax[1] = EXUstd::Maximum(pref[1], pmax[1]); - pmax[2] = EXUstd::Maximum(pref[2], pmax[2]); - pmin[0] = EXUstd::Minimum(pref[0], pmin[0]); - pmin[1] = EXUstd::Minimum(pref[1], pmin[1]); - pmin[2] = EXUstd::Minimum(pref[2], pmin[2]); - } - - } - } - //check if some bad coordinates result - if (pmax == pmax0 || pmin == pmin0) - { - pmin = Vector3D({ 0.,0.,0. }); - pmax = Vector3D({ 1.,1.,1. }); - } - else if (pmax == pmin) - { - Real d = 0.5; - pmax += Vector3D({ d,d,d }); - pmin -= Vector3D({ d,d,d}); - } - Vector3D center = 0.5*(pmin + pmax); - - if (renderState.centerPoint[0] == 0 && renderState.centerPoint[1] == 0 && renderState.centerPoint[2] == 0) { - renderState.centerPoint.CopyFrom(center); - } - - renderState.maxSceneSize = (float)((pmax - pmin).GetL2Norm()); - if (renderState.maxSceneSize < settings.general.minSceneSize) - { - renderState.maxSceneSize = settings.general.minSceneSize; - } - renderState.zoom = 0.5f*renderState.maxSceneSize; - } + ////for now, use nodal reference coordinates to estimate the maximum zoom level + //Vector3D pmax0({ -1e30,-1e30,-1e30 }); + //Vector3D pmin0({ 1e30,1e30,1e30 }); + //Vector3D pmax = pmax0; + //Vector3D pmin = pmin0; + //for (auto visSystem : visualizationSystems) + //{ + // //! @todo extend VisualizationSystemContainer::InitializeView for objects, markers and loads; maybe better to first draw all and zoom to full region? + // for (auto item : visSystem->systemData->GetCNodes()) + // { + // if ((Index)item->GetNodeGroup() & (Index)CNodeGroup::ODE2variables) + // { + // //LinkedDataVector pref = item->GetReferenceCoordinateVector(); + // Vector3D pref = ((CNodeODE2*)item)->GetPosition(ConfigurationType::Reference); + + // pmax[0] = EXUstd::Maximum(pref[0], pmax[0]); + // pmax[1] = EXUstd::Maximum(pref[1], pmax[1]); + // pmax[2] = EXUstd::Maximum(pref[2], pmax[2]); + // pmin[0] = EXUstd::Minimum(pref[0], pmin[0]); + // pmin[1] = EXUstd::Minimum(pref[1], pmin[1]); + // pmin[2] = EXUstd::Minimum(pref[2], pmin[2]); + // } + + // } + //} + ////check if some bad coordinates result + //if (pmax == pmax0 || pmin == pmin0) + //{ + // pmin = Vector3D({ 0.,0.,0. }); + // pmax = Vector3D({ 1.,1.,1. }); + //} + //else if (pmax == pmin) + //{ + // Real d = 0.5; + // pmax += Vector3D({ d,d,d }); + // pmin -= Vector3D({ d,d,d}); + //} + //Vector3D center = 0.5*(pmin + pmax); + + //if (renderState.centerPoint[0] == 0 && renderState.centerPoint[1] == 0 && renderState.centerPoint[2] == 0) { + // renderState.centerPoint.CopyFrom(center); + //} + + //renderState.maxSceneSize = (float)((pmax - pmin).GetL2Norm()); + //if (renderState.maxSceneSize < settings.general.minSceneSize) + //{ + // renderState.maxSceneSize = settings.general.minSceneSize; + //} + + //if (settings.general.autoFitScene) + //{ + // renderState.zoom = 0.4f*renderState.maxSceneSize; + //} } //! any multi-line text message from computation to be shown in renderer (e.g. time, solver, ...) diff --git a/main/src/Graphics/VisualizationSystemContainer.h b/main/src/Graphics/VisualizationSystemContainer.h index 79460d5c..d507dcc1 100644 --- a/main/src/Graphics/VisualizationSystemContainer.h +++ b/main/src/Graphics/VisualizationSystemContainer.h @@ -114,7 +114,8 @@ class VisualizationSystemContainer: public VisualizationSystemContainerBase VisualizationSettings settings; //!< general settings for visualization RenderState renderState; //!< Data linked to state variables of the OpenGL engine (e.g. zoom, transformation matrices, ...) ResizableArray visualizationSystems; //! linked to all visualization systems (placed in MainSystem); links need to be kept up-to-date by MainSystem Add/Delete - bool zoomAllRequest; //! used to perform UpdateMaximumSceneCoordinates() + bool zoomAllRequest; //! used to perform zoom all() + bool computeMaxSceneRequest; //! used to update max scene coordinates and center bool updateGraphicsDataNow; //! renderer signals to update the graphics data, e.g. if settings have changed; reset to false after UpdateGraphicsData(...) is called std::string computationMessage; //! message of computation to be shown in renderer window bool saveImage; //!< set true: signal to save the current state shall be rendered and saved to a given image (with consecutive number); will be set false, as soon as frame is saved @@ -127,6 +128,7 @@ class VisualizationSystemContainer: public VisualizationSystemContainerBase VisualizationSystemContainer() { zoomAllRequest = false; + computeMaxSceneRequest = true; //always done at beginning! saveImage = false; saveImageOpenGL = false; updateGraphicsDataNowInternal = false; @@ -202,7 +204,7 @@ class VisualizationSystemContainer: public VisualizationSystemContainerBase //virtual void SetVisualizationIsRunning(bool flag = true) override; //! if the system has changed or loaded, compute maximum box of all items and reset scene to the maximum box - virtual void UpdateMaximumSceneCoordinates() override; + virtual void InitializeView() override; //! renderer signals to update the graphics data, e.g. if settings have changed virtual void UpdateGraphicsDataNow() override @@ -230,6 +232,11 @@ class VisualizationSystemContainer: public VisualizationSystemContainerBase return false; } + virtual void SetZoomAllRequest(bool flag) override { zoomAllRequest = flag; } + + virtual void SetComputeMaxSceneRequest(bool flag) override { computeMaxSceneRequest = flag; } + virtual bool GetComputeMaxSceneRequest() override { return computeMaxSceneRequest; } + //! any multi-line text message from computation to be shown in renderer (e.g. time, solver, ...) virtual std::string GetComputationMessage(bool solverInformation = true, bool solutionInformation = true, bool solverTime = true) override; diff --git a/main/src/Graphics/VisualizationSystemContainerBase.h b/main/src/Graphics/VisualizationSystemContainerBase.h index d478444a..fb2de44a 100644 --- a/main/src/Graphics/VisualizationSystemContainerBase.h +++ b/main/src/Graphics/VisualizationSystemContainerBase.h @@ -28,7 +28,7 @@ class VisualizationSystemContainerBase public: //! OpenGL renderer sends message that graphics shall be updated virtual void UpdateGraphicsData() = 0; //!< renderer reports to simulation to update the graphics data - virtual void UpdateMaximumSceneCoordinates() = 0; //!< renderer reports to update the maximum scene coordinates (on initialization) + virtual void InitializeView() = 0; //!< renderer reports to update the maximum scene coordinates (on initialization) virtual void StopSimulation() = 0; //!< renderer reports to simulation that simulation shall be interrupted virtual void ForceQuitSimulation(bool flag = true) = 0; //!< renderer reports that render window is closed and simulation shall be shut down virtual void ContinueSimulation() = 0; //!< renderer reports to simulation that simulation can be continued @@ -37,12 +37,15 @@ class VisualizationSystemContainerBase virtual void SaveImageFinished() = 0; //! renderer signals that frame has been grabed and saved virtual bool SaveImageRequest() = 0; //! signal renderer that a frame shall be recorded virtual bool GetAndResetZoomAllRequest() = 0;//! get zoom all request and reset to false - virtual std::string GetComputationMessage(bool solverInformation = true, + virtual void SetComputeMaxSceneRequest(bool flag) = 0; + virtual bool GetComputeMaxSceneRequest() = 0; + + virtual std::string GetComputationMessage(bool solverInformation = true, bool solutionInformation = true, bool solverTime = true) = 0; //! any multi-line text message from computation to be shown in renderer (e.g. time, solver, ...) virtual MainSystem* GetMainSystemBacklink(Index iSystem) = 0; //! REMOVE: get backlink of ith main system (0 if not existing), temporary for selection virtual Index NumberOFMainSystemsBacklink() const = 0; //! REMOVE: get backlink to number of main systems, temporary for selection virtual bool DoIdleOperations() = 0; //!< this function does any idle operations (execute some python commands) and returns false if stop flag in the render engine, otherwise true; - + virtual void SetZoomAllRequest(bool flag) = 0; //!< request ZoomAll virtual ~VisualizationSystemContainerBase() {} //added for correct deletion of derived classes @@ -77,7 +80,8 @@ class RenderState { public: //GLfloat modelview[16]; //current model view matrix - Float3 centerPoint; //offset of scene in x, y and z direction; initialized by user, then by UpdateMaximumSceneCoordinates and hereafter changed in OpenGL renderer by ZoomAll (z not used, because it would bring objects out of near/far plane) + Float3 centerPoint; //offset of scene in x, y and z direction; initialized by user, then by InitializeView and hereafter changed in OpenGL renderer by ZoomAll (z not used, because it would bring objects out of near/far plane) + //Float3 rotationCenterPoint; //additional offset for point around which the model view is rotated; standard=[0,0,0] float maxSceneSize; //size given e.g. by initial state of system float zoom; //this is a factor for zoom diff --git a/main/src/Linalg/SlimVector.h b/main/src/Linalg/SlimVector.h index eb79c499..2d758b5c 100644 --- a/main/src/Linalg/SlimVector.h +++ b/main/src/Linalg/SlimVector.h @@ -490,7 +490,23 @@ class SlimVectorBase for (auto &item : *this) { item *= norm; } //changed from "item /= norm" to be compatible with autodiff } - T& X() + ////! get sum of components + //T Sum() const + //{ + // T result = 0.; + // for (auto item : *this) { result += item; } + // return result; + //} + + //! get sum of absolute values + T SumAbs() const + { + T result = 0.; + for (auto item : *this) { result += fabs(item); } + return result; + } + + T& X() { static_assert(dataSize >= 1, "ERROR: SlimVectorBase dataSize < 1 for function T& X()"); return data[0]; diff --git a/main/src/Main/CSystem.cpp b/main/src/Main/CSystem.cpp index 85758c2b..1fa1853c 100644 --- a/main/src/Main/CSystem.cpp +++ b/main/src/Main/CSystem.cpp @@ -2054,23 +2054,22 @@ void CSystem::JacobianODE2RHS(TemporaryComputationDataArray& tempArray, const Nu { ArrayIndex& ltgODE2 = cSystemData.GetLocalToGlobalODE2()[j]; Index nLocalODE2 = ltgODE2.NumberOfItems(); - f0.SetNumberOfItems(nLocalODE2); - f1.SetNumberOfItems(nLocalODE2); JacobianType::Type jacType = object->GetAvailableJacobians(); bool jacobianComputed = false; - if (jacType & (JacobianType::ODE2_ODE2 + JacobianType::ODE2_ODE2_t)) //any ODE2 dependency + if (jacType & (JacobianType::ODE2_ODE2 + JacobianType::ODE2_ODE2_t + JacobianType::ODE2_ODE1)) //any ODE2 dependency { - if (!numDiff.forODE2 && ((jacType & (JacobianType::ODE2_ODE2_function + JacobianType::ODE2_ODE2_t_function)) != 0)) + if (!numDiff.forODE2 && ((jacType & (JacobianType::ODE2_ODE2_function + JacobianType::ODE2_ODE2_t_function/* + JacobianType::ODE2_ODE1_function*/)) != 0)) { if (!EXUstd::IsOfType(object->GetType(), CObjectType::Connector)) - { //*** compute object jacobian, e.g., finite element or rigid body + { // ++++++++++++++ compute object jacobian, e.g., finite element or rigid body jacobianComputed = true; //matrix size set inside object object->ComputeJacobianODE2_ODE2(temp.jacobianODE2Container, temp.jacobianTemp, -factorODE2, -factorODE2_t, j, ltgODE2); //minus (-) because in numerical mode, f0-f1 leads to negative sign (RHS ==> LHS) + //ODE2_ODE1 missing here! if (temp.jacobianODE2Container.UseDenseMatrix()) { jacobianGM.AddSubmatrix(temp.jacobianODE2Container.GetInternalDenseMatrix(), 1., ltgODE2, ltgODE2); @@ -2084,7 +2083,7 @@ void CSystem::JacobianODE2RHS(TemporaryComputationDataArray& tempArray, const Nu } } //if (!EXUstd::IsOfType(object->GetType(), CObjectType::Connector) else if (!numDiff.forODE2connectors) - { //*** go the lengthier way: compute connector jacobian, e.g., spring-damper + { // ++++++++++++++ go the lengthier way: compute connector jacobian, e.g., spring-damper CObjectConnector* connector = (CObjectConnector*)object; const ArrayIndex& markerNumbers = connector->GetMarkerNumbers(); @@ -2143,59 +2142,97 @@ void CSystem::JacobianODE2RHS(TemporaryComputationDataArray& tempArray, const Nu } //if (numDiff.forODE2connectors) } - if (!jacobianComputed && ComputeObjectODE2LHS(temp, object, f0, j)) //check if it is a constraint, etc. which is not differentiated for ODE2 jacobian + + if (!jacobianComputed) { - localJacobian.SetNumberOfRowsAndColumns(nLocalODE2, nLocalODE2); //needs not to be initialized, because the matrix is fully computed and then added to jacobianGM - if (diffODE2) + f0.SetNumberOfItems(nLocalODE2); //size also correct for ODE1 derivatives + f1.SetNumberOfItems(nLocalODE2); + if (ComputeObjectODE2LHS(temp, object, f0, j)) //check if it is a constraint, etc. which is not differentiated for ODE2 jacobian { - Real xRefVal = 0; - for (Index i = 0; i < nLocalODE2; i++) //differentiate w.r.t. every ltgODE2 coordinate + localJacobian.SetNumberOfRowsAndColumns(nLocalODE2, nLocalODE2); //needs not to be initialized, because the matrix is fully computed and then added to jacobianGM + if (diffODE2) { - Real& xVal = x[ltgODE2[i]]; - if (numDiff.addReferenceCoordinatesToEpsilon) { xRefVal = xRef[ltgODE2[i]]; } + Real xRefVal = 0; + for (Index i = 0; i < nLocalODE2; i++) //differentiate w.r.t. every ltgODE2 coordinate + { + Real& xVal = x[ltgODE2[i]]; + if (numDiff.addReferenceCoordinatesToEpsilon) { xRefVal = xRef[ltgODE2[i]]; } - eps = relEps * (EXUstd::Maximum(minCoord, fabs(xVal + xRefVal))); + eps = relEps * (EXUstd::Maximum(minCoord, fabs(xVal + xRefVal))); - xStore = xVal; - xVal += eps; - ComputeObjectODE2LHS(temp, object, f1, j); - xVal = xStore; + xStore = xVal; + xVal += eps; + ComputeObjectODE2LHS(temp, object, f1, j); + xVal = xStore; - epsInv = (1. / eps) * factorODE2; + epsInv = (1. / eps) * factorODE2; - for (Index k = 0; k < nLocalODE2; k++) - { - //use local jacobian: - localJacobian(k, i) = epsInv * (f0[k] - f1[k]); //-(f1-f0) == (f0-f1): negative sign, because object ODE2RHS is subtracted from global RHS-vector + for (Index k = 0; k < nLocalODE2; k++) + { + //use local jacobian: + localJacobian(k, i) = epsInv * (f0[k] - f1[k]); //-(f1-f0) == (f0-f1): negative sign, because object ODE2RHS is subtracted from global RHS-vector + } } } - } - else { localJacobian.SetAll(0.); } + else { localJacobian.SetAll(0.); } - if (diffODE2_t && EXUstd::IsOfType(jacType, JacobianType::ODE2_ODE2_t)) - { - for (Index i = 0; i < nLocalODE2; i++) //differentiate w.r.t. every ltgODE2 coordinate + if (diffODE2_t && EXUstd::IsOfType(jacType, JacobianType::ODE2_ODE2_t)) { - Real& xVal = x_t[ltgODE2[i]]; - eps = relEps * (EXUstd::Maximum(minCoord, fabs(xVal))); + for (Index i = 0; i < nLocalODE2; i++) //differentiate w.r.t. every ltgODE2 coordinate + { + Real& xVal = x_t[ltgODE2[i]]; + eps = relEps * (EXUstd::Maximum(minCoord, fabs(xVal))); + + xStore = xVal; + xVal += eps; + ComputeObjectODE2LHS(temp, object, f1, j); + xVal = xStore; + + epsInv = (1. / eps) * factorODE2_t; + + for (Index k = 0; k < nLocalODE2; k++) + { + //use local jacobian: + localJacobian(k, i) += epsInv * (f0[k] - f1[k]); //-(f1-f0) == (f0-f1): negative sign, because object ODE2RHS is subtracted from global RHS-vector + } + } + } + + jacobianGM.AddSubmatrix(localJacobian, 1., ltgODE2, ltgODE2); + //pout << "jacN" << j << "=np.array(" << localJacobian << ")\n"; - xStore = xVal; - xVal += eps; - ComputeObjectODE2LHS(temp, object, f1, j); - xVal = xStore; + if (diffODE1 && (jacType & JacobianType::ODE2_ODE1)) + { + ArrayIndex& ltgODE1 = cSystemData.GetLocalToGlobalODE1()[j]; + Index nLocalODE1 = ltgODE1.NumberOfItems(); - epsInv = (1. / eps) * factorODE2_t; + localJacobian.SetNumberOfRowsAndColumns(nLocalODE2, nLocalODE1); //needs not to be initialized, because the matrix is fully computed and then added to jacobianGM - for (Index k = 0; k < nLocalODE2; k++) + Real xRefVal = 0; + for (Index i = 0; i < nLocalODE1; i++) //differentiate w.r.t. every ltgODE1 coordinate { - //use local jacobian: - localJacobian(k, i) += epsInv * (f0[k] - f1[k]); //-(f1-f0) == (f0-f1): negative sign, because object ODE2RHS is subtracted from global RHS-vector + Real& xVal = xODE1[ltgODE1[i]]; + if (numDiff.addReferenceCoordinatesToEpsilon) { xRefVal = xRefODE1[ltgODE1[i]]; } + + eps = relEps * (EXUstd::Maximum(minCoord, fabs(xVal + xRefVal))); + + xStore = xVal; + xVal += eps; + ComputeObjectODE2LHS(temp, object, f1, j); + xVal = xStore; + + epsInv = (1. / eps) * factorODE1; + + for (Index k = 0; k < nLocalODE2; k++) + { + //use local jacobian: + localJacobian(k, i) = epsInv * (f0[k] - f1[k]); //-(f1-f0) == (f0-f1): negative sign, because object ODE1RHS is subtracted from global RHS-vector + } } + //pout << "locJacODE1=" << localJacobian << "\n"; + jacobianGM.AddSubmatrix(localJacobian, 1., ltgODE2, ltgODE1, 0, nODE2); //fill into ODE2 rows, ODE1 columns } } - - jacobianGM.AddSubmatrix(localJacobian, 1., ltgODE2, ltgODE2); - //pout << "jacN" << j << "=np.array(" << localJacobian << ")\n"; } } }//isActive @@ -2253,9 +2290,6 @@ void CSystem::JacobianODE2RHS(TemporaryComputationDataArray& tempArray, const Nu { //++++++++++++++++++++++++++++++++++++++++++++++++ //for ODE2-ODE1: - f0.SetNumberOfItems(nODE2); - f1.SetNumberOfItems(nODE2); - ComputeSystemODE2RHS(tempArray, f0); //compute nominal value for jacobian Real xRefVal = 0; for (Index i = 0; i < nODE1; i++) //compute column i @@ -2321,9 +2355,11 @@ void CSystem::NumericalJacobianODE1RHS(TemporaryComputationDataArray& tempArray, Vector& xODE2_t = cSystemData.GetCData().currentState.ODE2Coords_t; //for diff w.r.t. velocities + bool diffODE1 = (factorODE1 != 0. && nODE1 != 0); bool diffODE2 = (factorODE2 != 0. && nODE2 != 0); bool diffODE2_t = (factorODE2_t != 0. && nODE2 != 0); - + //diffODE2 = false; + //diffODE2_t = false; if (!numDiff.doSystemWideDifferentiation) { @@ -2437,21 +2473,24 @@ void CSystem::NumericalJacobianODE1RHS(TemporaryComputationDataArray& tempArray, Real xRefVal = 0; //for ODE1-ODE1: - for (Index i = 0; i < nODE1; i++) //compute column i + if (diffODE1) { - if (numDiff.addReferenceCoordinatesToEpsilon) { xRefVal = xRefODE1[i]; } - eps = relEps * (EXUstd::Maximum(minCoord, fabs(xODE1[i] + xRefVal))); + for (Index i = 0; i < nODE1; i++) //compute column i + { + if (numDiff.addReferenceCoordinatesToEpsilon) { xRefVal = xRefODE1[i]; } + eps = relEps * (EXUstd::Maximum(minCoord, fabs(xODE1[i] + xRefVal))); - xStore = xODE1[i]; - xODE1[i] += eps; - ComputeSystemODE1RHS(temp, f1); - xODE1[i] = xStore; + xStore = xODE1[i]; + xODE1[i] += eps; + ComputeSystemODE1RHS(temp, f1); + xODE1[i] = xStore; - epsInv = (1. / eps) * factorODE1; + epsInv = (1. / eps) * factorODE1; - f1 -= f0; - f1 *= epsInv; - jacobianGM.AddColumnVector(nODE2 + i, f1, rowOffset);//add rowOffset argument to AddColumnVector(..) + f1 -= f0; + f1 *= epsInv; + jacobianGM.AddColumnVector(nODE2 + i, f1, rowOffset);//add rowOffset argument to AddColumnVector(..) + } } //++++++++++++++++++++++++++++++++++++++++++++++++ //for ODE1-ODE2: @@ -2489,7 +2528,7 @@ void CSystem::NumericalJacobianODE1RHS(TemporaryComputationDataArray& tempArray, f1 -= f0; f1 *= epsInv; - jacobianGM.AddColumnVector(i, f1); + jacobianGM.AddColumnVector(i, f1, rowOffset); } } } @@ -2561,15 +2600,8 @@ void CSystem::NumericalJacobianAE(TemporaryComputationData& temp, const Numerica for (Index j = 0; j < nAE; j++) { Real x = epsInv * (f1[j] - f0[j]); - //if (fillIntoSystemMatrix) - //{ jacobian(offsetAE + j, i) = factorAE_ODE2 * x; //add Cq ==> factor only used for Position constraints ... jacobian(i, offsetAE + j) = factorODE2_AE * x; //add CqT ==> new factor - //} - //else - //{ - // jacobian(j, i) = /*factorAE_ODE2 * */ x; //add Cq which is lateron used as transposed matrix; factor is usually 1 in this case - //} } } diff --git a/main/src/Main/MainSystem.cpp b/main/src/Main/MainSystem.cpp index ee11daa2..bed77365 100644 --- a/main/src/Main/MainSystem.cpp +++ b/main/src/Main/MainSystem.cpp @@ -52,6 +52,12 @@ void MainSystem::Reset() //mainSystemIndex = -1; //... check if this is correctly set? test several SC.Reset and similar operations ==> this MainSystem would not be usable any more, as it is not linked to SystemContainer } +void MainSystem::SystemHasChanged() +{ + GetCSystem()->SystemHasChanged(); + GetVisualizationSystem().SetSystemHasChanged(true); +} + MainSystemContainer& MainSystem::GetMainSystemContainer() { return *mainSystemContainerBacklink; @@ -181,7 +187,7 @@ void MainSystem::RaiseIfNotConsistent(const char* functionName) const //! this is the hook to the object factory, handling all kinds of objects, nodes, ... Index MainSystem::AddMainNode(py::dict d) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); Index ind = GetMainObjectFactory().AddMainNode(*this, d); InteractiveModeActions(); return ind; @@ -281,7 +287,7 @@ void MainSystem::PyModifyNode(const py::object& itemIndex, py::dict nodeDict) Index nodeNumber = EPyUtils::GetNodeIndexSafely(itemIndex); if (nodeNumber < mainSystemData.GetMainNodes().NumberOfItems()) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); mainSystemData.GetMainNodes().GetItem(nodeNumber)->SetWithDictionary(nodeDict); InteractiveModeActions(); } @@ -475,7 +481,7 @@ void MainSystem::PySetNodeParameter(const py::object& itemIndex, const STDstring //! this is the hook to the object factory, handling all kinds of objects, nodes, ... Index MainSystem::AddMainObject(py::dict d) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); Index ind = GetMainObjectFactory().AddMainObject(*this, d); InteractiveModeActions(); @@ -561,7 +567,7 @@ void MainSystem::PyModifyObject(const py::object& itemIndex, py::dict d) Index itemNumber = EPyUtils::GetObjectIndexSafely(itemIndex); if (itemNumber < mainSystemData.GetMainObjects().NumberOfItems()) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); mainSystemData.GetMainObjects().GetItem(itemNumber)->SetWithDictionary(d); InteractiveModeActions(); } @@ -731,7 +737,7 @@ void MainSystem::PySetObjectParameter(const py::object& itemIndex, const STDstri //! this is the hook to the object factory, handling all kinds of objects, nodes, ... Index MainSystem::AddMainMarker(py::dict d) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); Index ind = GetMainObjectFactory().AddMainMarker(*this, d); InteractiveModeActions(); return ind; @@ -817,7 +823,7 @@ void MainSystem::PyModifyMarker(const py::object& itemIndex, py::dict d) Index itemNumber = EPyUtils::GetMarkerIndexSafely(itemIndex); if (itemNumber < mainSystemData.GetMainMarkers().NumberOfItems()) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); mainSystemData.GetMainMarkers().GetItem(itemNumber)->SetWithDictionary(d); InteractiveModeActions(); } @@ -893,7 +899,7 @@ void MainSystem::PySetMarkerParameter(const py::object& itemIndex, const STDstri //! this is the hook to the object factory, handling all kinds of objects, nodes, ... Index MainSystem::AddMainLoad(py::dict d) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); Index ind = GetMainObjectFactory().AddMainLoad(*this, d); InteractiveModeActions(); return ind; @@ -979,7 +985,7 @@ void MainSystem::PyModifyLoad(const py::object& itemIndex, py::dict d) Index itemNumber = EPyUtils::GetLoadIndexSafely(itemIndex); if (itemNumber < mainSystemData.GetMainLoads().NumberOfItems()) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); mainSystemData.GetMainLoads().GetItem(itemNumber)->SetWithDictionary(d); InteractiveModeActions(); } @@ -1072,7 +1078,7 @@ void MainSystem::PySetLoadParameter(const py::object& itemIndex, const STDstring //! this is the hook to the object factory, handling all kinds of objects, nodes, ... Index MainSystem::AddMainSensor(py::dict d) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); Index ind = GetMainObjectFactory().AddMainSensor(*this, d); InteractiveModeActions(); return ind; @@ -1158,7 +1164,7 @@ void MainSystem::PyModifySensor(const py::object& itemIndex, py::dict d) Index itemNumber = EPyUtils::GetSensorIndexSafely(itemIndex); if (itemNumber < mainSystemData.GetMainSensors().NumberOfItems()) { - GetCSystem()->SystemHasChanged(); + SystemHasChanged(); mainSystemData.GetMainSensors().GetItem(itemNumber)->SetWithDictionary(d); InteractiveModeActions(); } diff --git a/main/src/Main/MainSystem.h b/main/src/Main/MainSystem.h index c01dd2b9..9384ebd2 100644 --- a/main/src/Main/MainSystem.h +++ b/main/src/Main/MainSystem.h @@ -81,6 +81,10 @@ class MainSystem: public MainSystemBase //! backlink to MainSystemContainer; add const as it cannot be distinguished by pybind11 const MainSystemContainer& GetMainSystemContainerConst() const; + //! signal CSystem and VisualizationSystem that there are new items; system becomes invalid; + //! visualization system needs to update maxSceneSize and center + void SystemHasChanged(); + //DELETE: void Test() const { int i = 1; }; VisualizationSystem& GetVisualizationSystem() { return visualizationSystem; } @@ -158,7 +162,7 @@ class MainSystem: public MainSystemBase void Assemble() { cSystem->Assemble(*this); - //visualizationSystem.UpdateMaximumSceneCoordinates(); //uses reference coordinates to obtain the scene center and its size + //visualizationSystem.InitializeView(); //uses reference coordinates to obtain the scene center and its size } void AssembleCoordinates() { cSystem->AssembleCoordinates(*this); } void AssembleLTGLists() { cSystem->AssembleLTGLists(*this); } diff --git a/main/src/Main/MainSystemContainer.cpp b/main/src/Main/MainSystemContainer.cpp index 7c6eb054..8dd4f021 100644 --- a/main/src/Main/MainSystemContainer.cpp +++ b/main/src/Main/MainSystemContainer.cpp @@ -32,6 +32,7 @@ py::dict MainSystemContainer::RenderState2PyDict(const RenderState& state) { auto d = py::dict(); d["centerPoint"] = (const std::vector)state.centerPoint; + //d["rotationCenterPoint"] = (const std::vector)state.rotationCenterPoint; d["maxSceneSize"] = state.maxSceneSize; d["zoom"] = state.zoom; d["currentWindowSize"] = (const std::vector)state.currentWindowSize; @@ -41,7 +42,7 @@ py::dict MainSystemContainer::RenderState2PyDict(const RenderState& state) //Float9 A33({ A[0], A[1], A[2], A[4], A[5], A[6], A[8], A[9], A[10] }); //convert 4x4 into 3x3 matrix as position part of A is [0,0,0] //d["modelRotation"] = EXUmath::SlimVectorF9ToStdArray33F(A33); - Matrix3DF rotMatrix(3, 3, { A[0], A[1], A[2], A[4], A[5], A[6], A[8], A[9], A[10] }); + //Matrix3DF rotMatrix(3, 3, { A[0], A[1], A[2], A[4], A[5], A[6], A[8], A[9], A[10] }); //++++++++++++++++++++++++++++++++++++++++++++ //old, with numpy, gives problems in output ("array( ...", "dtype=float32") @@ -86,8 +87,11 @@ void MainSystemContainer::PySetRenderState(py::dict renderState) RenderState& state = visualizationSystems.renderState; //Vector3D centerPoint; - EPyUtils::SetSlimVectorTemplateSafely(renderState["centerPoint"], state.centerPoint); - + EPyUtils::SetSlimVectorTemplateSafely(renderState["centerPoint"], state.centerPoint); + //if (renderState.contains("rotationCenterPoint")) + //{ + // EPyUtils::SetSlimVectorTemplateSafely(renderState["rotationCenterPoint"], state.rotationCenterPoint); + //} state.maxSceneSize = py::cast(renderState["maxSceneSize"]); state.zoom = py::cast(renderState["zoom"]); diff --git a/main/src/Objects/CNodePoint3DSlope23.cpp b/main/src/Objects/CNodePoint3DSlope23.cpp index 5b9294de..ecd643a3 100644 --- a/main/src/Objects/CNodePoint3DSlope23.cpp +++ b/main/src/Objects/CNodePoint3DSlope23.cpp @@ -60,7 +60,7 @@ void fRotTest(const ConstSizeVectorBase& q, ConstSizeVectorBase q0; @@ -143,7 +143,7 @@ Matrix3D CNodePoint3DSlope23::GetRotationMatrix(ConfigurationType configuration) //! AUTO: return configuration dependent velocity of node; returns always a 3D Vector Vector3D CNodePoint3DSlope23::GetAngularVelocity(ConfigurationType configuration) const { - CHECKandTHROWstring("CNodePoint3DSlope23::GetAngularVelocity: untested!"); + //CHECKandTHROWstring("CNodePoint3DSlope23::GetAngularVelocity: untested!"); ConstSizeVector q; q.CopyFrom(GetCoordinateVector(ConfigurationType::Reference)); @@ -174,14 +174,14 @@ Vector3D CNodePoint3DSlope23::GetAngularVelocity(ConfigurationType configuration //! AUTO: return configuration dependent velocity of node; returns always a 3D Vector Vector3D CNodePoint3DSlope23::GetAngularVelocityLocal(ConfigurationType configuration) const { - CHECKandTHROWstring("CNodePoint3DSlope23::GetAngularVelocityLocal: untested!"); + //CHECKandTHROWstring("CNodePoint3DSlope23::GetAngularVelocityLocal: untested!"); return GetRotationMatrix(configuration).GetTransposed() * GetAngularVelocity(configuration); } void CNodePoint3DSlope23::GetRotationJacobian(Matrix& value) const { - CHECKandTHROWstring("CNodePoint3DSlope23::GetRotationJacobian: untested!"); + //CHECKandTHROWstring("CNodePoint3DSlope23::GetRotationJacobian: untested!"); ConstSizeVector q; diff --git a/main/src/Solver/CSolverImplicitSecondOrder.cpp b/main/src/Solver/CSolverImplicitSecondOrder.cpp index 41541b1c..a0c90ec6 100644 --- a/main/src/Solver/CSolverImplicitSecondOrder.cpp +++ b/main/src/Solver/CSolverImplicitSecondOrder.cpp @@ -302,9 +302,6 @@ void CSolverImplicitSecondOrderTimeInt::PreInitializeSolverSpecific(CSystem& com //! post-initialize for solver specific tasks; called at the end of InitializeSolver void CSolverImplicitSecondOrderTimeInt::PostInitializeSolverSpecific(CSystem& computationalSystem, const SimulationSettings& simulationSettings) { - //now implemented - //if (data.nODE1 != 0) { SysError("SolverImplicitSecondOrder cannot solve first order differential equations (ODE1) for now", file.solverFile); } - if (IsVerbose(2)) { if (simulationSettings.timeIntegration.generalizedAlpha.useNewmark) @@ -545,7 +542,7 @@ void CSolverImplicitSecondOrderTimeInt::ComputeNewtonJacobian(CSystem& computati //Tangent stiffness //K-Matrix; has no factor computationalSystem.JacobianODE2RHS(data.tempCompDataArray, newton.numericalDifferentiation, *(data.systemJacobian), - -1. * scalODE2, -gammaPrime * scalODE2, scalODE1); //RHS ==> -K + -scalODE2, -gammaPrime * scalODE2, -scalODE2); //RHS ==> -K; Residuals are scaled ==> scale also derivatives of ODE1 variables with scalODE2; time derivative additionally has factor gammaPrime STOPTIMER(timer.jacobianODE2); //+++++++++++++++++++++++++++++ @@ -554,7 +551,7 @@ void CSolverImplicitSecondOrderTimeInt::ComputeNewtonJacobian(CSystem& computati //Tangent stiffness: for ODE1 part, the jacobian is de facto computed for RHS while the ODE2 jacobian is put to LHS by multiplying with (-1) //ODE1 K-Matrix; has no factor computationalSystem.NumericalJacobianODE1RHS(data.tempCompDataArray, newton.numericalDifferentiation, - *(data.systemJacobian), scalODE1, gammaPrime * scalODE1, scalODE1); //RHS ==> K_ODE1; no scaling for now + *(data.systemJacobian), scalODE1, gammaPrime * scalODE1, scalODE1); //RHS ==> K_ODE1; no scaling for now; time derivative additionally has factor gammaPrime data.systemJacobian->AddDiagonalMatrix(-2./ it.currentStepSize, data.nODE1, data.nODE2, data.nODE2); //for qODE1_t part STOPTIMER(timer.jacobianODE1); diff --git a/main/src/Utilities/BasicFunctions.h b/main/src/Utilities/BasicFunctions.h index 8e3cc644..6386d2c4 100644 --- a/main/src/Utilities/BasicFunctions.h +++ b/main/src/Utilities/BasicFunctions.h @@ -293,6 +293,26 @@ namespace EXUstd { return value; } + inline float GetSafelyUFloat(float value, const char* parameterName) + { + if (value < 0) + { + PyError(STDstring("float parameter '") + parameterName + "' may not be negative, but received: " + EXUstd::ToString(value)); + return 0; + } + return value; + } + + inline float GetSafelyPFloat(float value, const char* parameterName) + { + if (value <= 0) + { + PyError(STDstring("float parameter '") + parameterName + "' must be positive (> 0), but received: " + EXUstd::ToString(value)); + return 1; //any positive value, should work in most cases as a backup + } + return value; + } + //a function to wait until flag is available, then reserve flag inline void WaitAndLockSemaphore(std::atomic_flag& flag) { diff --git a/main/src/pythonGenerator/exudynVersion.py b/main/src/pythonGenerator/exudynVersion.py index 055628c6..d45aea3f 100644 --- a/main/src/pythonGenerator/exudynVersion.py +++ b/main/src/pythonGenerator/exudynVersion.py @@ -1,4 +1,4 @@ # version info automatically generated by tracker; generated by Johannes Gerstmayr -# last modified = 2022-06-17 -exudynVersionString = "1.2.134.dev1" +# last modified = 2022-06-22 +exudynVersionString = "1.3.0" diff --git a/main/src/pythonGenerator/pythonAutoGenerateSystemStructures.py b/main/src/pythonGenerator/pythonAutoGenerateSystemStructures.py index 46c2084b..0f2d9cc7 100644 --- a/main/src/pythonGenerator/pythonAutoGenerateSystemStructures.py +++ b/main/src/pythonGenerator/pythonAutoGenerateSystemStructures.py @@ -12,7 +12,8 @@ sortStructures = True -typeCasts = {'Bool':'bool', 'Int':'Index', 'Real':'Real', 'UInt':'Index', 'PInt':'Index', 'UReal':'Real', 'PReal':'Real', +typeCasts = {'Bool':'bool', 'Int':'Index', 'Real':'Real', 'UInt':'Index', 'PInt':'Index', + 'UReal':'Real', 'PReal':'Real', 'UFloat':'float', 'PFloat':'float', 'Vector':'std::vector', 'Vector3D':'std::vector', #'Matrix':'Matrix', 'SymmetricMatrix':'Matrix', 'ArrayIndex':'std::vector', 'String':'std::string', 'FileName':'std::string', 'Float2': 'std::array', 'Float3': 'std::array', 'Float4': 'std::array', #e.g. for OpenGL vectors @@ -39,7 +40,10 @@ #return True for types, which get a range check and does a .def_property access in pybind and a set/get function def IsTypeWithRangeCheck(origType): - if origType.find('PInt') != -1 or origType.find('UInt') != -1 or origType.find('PReal') != -1 or origType.find('UReal') != -1: + if (origType.find('PInt') != -1 or origType.find('UInt') != -1 or + origType.find('PReal') != -1 or origType.find('UReal') != -1 or + origType.find('PFloat') != -1 or origType.find('UFloat') != -1 + ): return True return False @@ -690,7 +694,9 @@ def CleanPyDocStrings(s): fileLines = file.readlines() - typeConversion = {'Bool':'bool', 'Int':'Index', 'Real':'Real', 'UInt':'Index', 'PInt':'Index', 'UReal':'Real', 'PReal':'Real', 'Vector':'Vector', + typeConversion = {'Bool':'bool', 'Int':'Index', 'Real':'Real', 'UInt':'Index', 'PInt':'Index', + 'UReal':'Real', 'PReal':'Real', 'UFloat':'float', 'PFloat':'float', + 'Vector':'Vector', 'Matrix':'Matrix', 'SymmetricMatrix':'Vector', 'NumpyMatrix':'py::array_t', 'NumpyVector':'py::array_t', 'String':'std::string', 'FileName':'std::string', diff --git a/main/src/pythonGenerator/systemStructuresDefinition.py b/main/src/pythonGenerator/systemStructuresDefinition.py index f99cf474..25bf0705 100644 --- a/main/src/pythonGenerator/systemStructuresDefinition.py +++ b/main/src/pythonGenerator/systemStructuresDefinition.py @@ -348,7 +348,7 @@ class = VSettingsGeneral classDescription = "General settings for visualization." #V|F, pythonName, cplusplusName, size, type, defaultValue,args, cFlags, parameterDescription V, graphicsUpdateInterval, , , float, "0.1f", , P, "interval of graphics update during simulation in seconds; 0.1 = 10 frames per second; low numbers might slow down computation speed" -V, autoFitScene, , , bool, true, , P, "automatically fit scene within first second after StartRenderer()" +V, autoFitScene, , , bool, true, , P, "automatically fit scene within startup after StartRenderer()" V, textSize, , , float, "12.f", , P, "general text size (font size) in pixels if not overwritten; if useWindowsMonitorScaleFactor=True, the the textSize is multplied with the windows monitor scaling factor for larger texts on on high resolution monitors; for bitmap fonts, the maximum size of any font (standard/large/huge) is limited to 256 (which is not recommended, especially if you do not have a powerful graphics card)" V, textColor, , 4, Float4, "Float4({0.f,0.f,0.f,1.0f})", , P, "general text color (default); used for system texts in render window" V, rendererPrecision, , , PInt, "4", , P, "precision of general floating point numbers shown in render window: total number of digits used (max. 16)" @@ -581,15 +581,19 @@ class = VSettingsOpenGL classDescription = "OpenGL settings for 2D and 2D rendering. For further details, see the OpenGL functionality" #V|F, pythonName, cplusplusName, size, type, defaultValue,args, cFlags, parameterDescription V, initialCenterPoint, , 3, Float3, "Float3({0.f,0.f,0.f})",, P, "centerpoint of scene (3D) at renderer startup; overwritten if autoFitScene = True" -V, initialZoom, , , float, "1.f", , P, "initial zoom of scene; overwritten/ignored if autoFitScene = True" -V, initialMaxSceneSize, , , float, "1.f", , P, "initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True" +V, initialZoom, , , UFloat, "1.f", , P, "initial zoom of scene; overwritten/ignored if autoFitScene = True" +V, initialMaxSceneSize, , , PFloat, "1.f", , P, "initial maximum scene size (auto: diagonal of cube with maximum scene coordinates); used for 'zoom all' functionality and for visibility of objects; overwritten if autoFitScene = True" V, initialModelRotation, , 3x3, StdArray33F, "EXUmath::Matrix3DFToStdArray33(Matrix3DF(3,3,{1.f,0.f,0.f, 0.f,1.f,0.f, 0.f,0.f,1.f}))", , P, "initial model rotation matrix for OpenGl; in python use e.g.: initialModelRotation=[[1,0,0],[0,1,0],[0,0,1]]" +#V, usePerspective, , , bool, false, , P, "if True, uses perspective drawing; use " +V, perspective, , , UFloat, "0.f", , P, "parameter prescribes amount of perspective (0=no perspective=orthographic projection; positive values increase perspective; feasible values are 0.001 (little perspective) ... 0.5 (large amount of perspective); mouse coordinates will not work with perspective" +V, shadow, , , UFloat, "0.f", , P, "parameter $\in [0 ... 1]$ prescribes amount of shadow; if this parameter is different from 1, rendering of triangles becomes approx.\ 5 times more expensive, so take care in case of complex scenes; for complex object, such as spheres with fine resolution or for particle systems, the present approach has limitations and leads to artifacts and unrealistic shadows" +V, shadowPolygonOffset, , , PFloat, "10.f", , P, "some special drawing parameter for shadows which should be handled with care; defines some offset needed by openGL to avoid aritfacts for shadows and depends on maxSceneSize" #V, initialModelRotation, , 9, Matrix3DF, "Matrix3DF(3,3,{1.f,0.f,0.f, 0.f,1.f,0.f, 0.f,0.f,1.f})", , P, "initial model rotation matrix for OpenGl; in Python use e.g.: initialModelRotation=[[1,0,0],[0,1,0],[0,0,1]]" # V, multiSampling, , 1, PInt, "1", , P, "multi sampling turned off (<=1) or turned on to given values (2, 4, 8 or 16); increases the graphics buffers and might crash due to graphics card memory limitations; only works if supported by hardware; if it does not work, try to change 3D graphics hardware settings!" -V, lineWidth, , 1, float, "1.f", , P, "width of lines used for representation of lines, circles, points, etc." +V, lineWidth, , 1, UFloat, "1.f", , P, "width of lines used for representation of lines, circles, points, etc." V, lineSmooth, , 1, bool, true, , P, "draw lines smooth" -V, textLineWidth, , 1, float, "1.f", , P, "width of lines used for representation of text" +V, textLineWidth, , 1, UFloat, "1.f", , P, "width of lines used for representation of text" V, textLineSmooth, , 1, bool, false, , P, "draw lines for representation of text smooth" V, facesTransparent, , 1, bool, false, , P, "True: show faces transparent independent of transparency (A)-value in color of objects; allow to show otherwise hidden node/marker/object numbers" V, showFaces, , 1, bool, true, , P, "show faces of triangles, etc.; using the options showFaces=false and showFaceEdges=true gives are wire frame representation" @@ -628,7 +632,7 @@ class = VSettingsOpenGL # debug: V, drawFaceNormals, , 1, bool, false, , P, "draws triangle normals, e.g. at center of triangles; used for debugging of faces" V, drawVertexNormals, , 1, bool, false, , P, "draws vertex normals; used for debugging" -V, drawNormalsLength, , 1, float, "0.1f", , P, "length of normals; used for debugging" +V, drawNormalsLength, , 1, PFloat, "0.1f", , P, "length of normals; used for debugging" # writeFile=VisualizationSettings.h @@ -667,6 +671,7 @@ class = VSettingsInteractive V, highlightColor, , 4, Float4, "Float4({0.8f,0.05f,0.05f,0.75f})",, P, "cRGB color for highlighted item; 4th value is alpha-transparency" V, highlightOtherColor, , 4, Float4, "Float4({0.5f,0.5f,0.5f,0.4f})", , P, "cRGB color for other items (which are not highlighted); 4th value is alpha-transparency" # +V, selectionHighlights, , , bool, true, , P, "True: mouse click highlights item (default: red)" V, selectionLeftMouse, , , bool, true, , P, "True: left mouse click on items and show basic information" V, selectionRightMouse, , , bool, true, , P, "True: right mouse click on items and show dictionary (read only!)" V, useJoystickInput, , , bool, true, , P, "True: read joystick input (use 6-axis joystick with lowest ID found when starting renderer window) and interpret as (x,y,z) position and (rotx, roty, rotz) rotation: as available from 3Dconnexion space mouse and maybe others as well; set to False, if external joystick makes problems ..."
line notes
1156renderState JGRAISED add description of render state from C++ into theDocDOCU2022-06-212022-08-20
1142 item functions checker
0972ContactFrictionCircleCable2DJGRAISED add / extend descriptionDOCU2022-03-092022-05-08
0971 Renderer
0968MarkerBodyCable2DShapeJGRAISED add offset from beam axis, to compute position, velocity and jacobians at contact surfaceEXTENSION2022-03-032022-05-02
0957 JointRevolute2D
0863RaspberryPi JGRAISED check compilation on Raspi, make adaptation of ngsolve includes to runEXTENSION2022-01-142022-03-15
0862 Vector alignment
0735parallel build JGRAISED check parallel build with MSbuild to reduce compilation timesCHECK2021-08-122021-10-11
0734 continuous integration
0677single threaded rendererJGRAISED correct crash with visualization dialog (MacOS)BUG2021-05-122021-07-11
0657 Delete item
1155center point JGRESOLVED add key "o" option to set center point to current center point of view; this allows to rotate around the current center point of the viewEXTENSION2022-06-212022-08-202022-06-21 18:16JG
1154Zoom all JGRESOLVED change procedures for zoom all and for computation of maximum scene coordinates; may affect appearance of your models; necessary for consistently computing perspective and shadow parametersCHANGE2022-06-212022-08-202022-06-21 08:38JG
1153noglfw JGRESOLVED check compilation without GLFWCHECK2022-06-202022-08-192022-06-20 10:58JG
1152Renderer JGRESOLVED add separate function to compute accurate scene size, store as 3D vector and as normEXTENSION2022-06-202022-08-192022-06-21 17:56JG
1151linux builds JGRESOLVED remove -g flag from linux builds, leading to 2.6MB instead of 38MB binaries; to enable debug information (e.g. to detect origin of some crashes, remove the -g0 flag in setup.py)CHANGE2022-06-192022-08-182022-06-19 18:34JG
1150OpenGL JGRESOLVED add shadows (simple)EXTENSION2022-06-182022-08-172022-06-20 01:49JGactivate with SC.VisualizationSettings().openGL.shadow, chosing a value between 0. and 1; good results obtained with 0.5
1149OpenGL JGRESOLVED add perspectiveEXTENSION2022-06-182022-08-172022-06-19 01:59JGadded openGL option perspective; EXPERIMENTAL!
1148jacobian ODE1 ODE2 JGRESOLVED fix jacobian computations for mixed ODE1-ODE2 components; check with HydraulicActuatorSimple (lower number of jacobians and iterations)FIX2022-06-182022-08-172022-06-18 23:38JG
1147 ODE1Coordinates_t
0972ContactFrictionCircleCable2DJGRESOLVED add / extend descriptionDOCU2022-03-092022-05-082022-06-22 07:44JG
0970 PlotSensor
0968MarkerBodyCable2DShapeJGRESOLVED add offset from beam axis, to compute position, velocity and jacobians at contact surfaceEXTENSION2022-03-032022-05-022022-06-22 07:46JGalready done earlier
0967 ANCFCable2D
0863RaspberryPi JGRESOLVED check compilation on Raspi, make adaptation of ngsolve includes to runEXTENSION2022-01-142022-03-152022-06-22 07:48JGalready done earlier
0857 GetInterpolatedSignalValue
0735parallel build JGRESOLVED check parallel build with MSbuild to reduce compilation timesCHECK2021-08-122021-10-112022-06-22 07:58JGalready done earlier
0733 ContactCoordinate
0677single threaded rendererJGRESOLVED correct crash with visualization dialog (MacOS)BUG2021-05-122021-07-112022-06-22 07:59JGnot resolved, but it is an issue of missing tkinter capabilities in MacOS
0676 single threaded renderer