├── .all-contributorsrc ├── .gitignore ├── .idea ├── ant.xml ├── codeStyles │ └── codeStyleConfig.xml ├── compiler.xml ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── libraries │ └── p5_4x.xml ├── misc.xml ├── modules.xml ├── nub.iml ├── uiDesigner.xml └── vcs.xml ├── README.md ├── assets ├── FreeSans-13.vlw ├── FreeSans-16.vlw ├── FreeSans-24.vlw ├── FreeSans-36.vlw └── PickingBuffer.frag ├── data ├── FreeSans-13.vlw ├── FreeSans-16.vlw ├── FreeSans-24.vlw ├── FreeSans-36.vlw ├── LinePicking.vert ├── Picking.frag └── PointPicking.vert ├── examples ├── basics │ ├── AuxiliaryViews │ │ └── AuxiliaryViews.pde │ ├── CajasOrientadas │ │ └── CajasOrientadas.pde │ ├── Eye │ │ └── Eye.pde │ ├── KeyFrames │ │ └── KeyFrames.pde │ ├── Luxo │ │ └── Luxo.pde │ ├── NodeFilters │ │ └── NodeFilters.pde │ ├── SceneBuffers │ │ └── SceneBuffers.pde │ └── SpaceNavigator │ │ ├── SpaceNavigator.pde │ │ └── data │ │ ├── rocket.mtl │ │ ├── rocket.obj │ │ ├── rocket.png │ │ └── world32k.jpg └── demos │ ├── CevaSonia │ ├── CevaSonia.pde │ └── data │ │ └── sonia.gif │ ├── CustomEyeInteraction │ ├── CustomEyeInteraction.pde │ └── data │ │ └── world32k.jpg │ ├── CustomNodeInteraction │ ├── CustomNodeInteraction.pde │ └── Torus.pde │ ├── DepthMap │ ├── DepthMap.pde │ └── data │ │ └── depth.glsl │ ├── FlockOfBoids │ ├── Boid.pde │ └── FlockOfBoids.pde │ ├── MiniMap │ └── MiniMap.pde │ ├── PostEffects │ ├── PostEffects.pde │ └── data │ │ ├── depth.glsl │ │ ├── edge.glsl │ │ ├── horizontal.glsl │ │ ├── kaleido.glsl │ │ ├── noise.glsl │ │ ├── pixelate.glsl │ │ └── raysfrag.glsl │ ├── ShadowMapping │ ├── ShadowMapping.pde │ └── data │ │ ├── depth_frag.glsl │ │ ├── shadow_frag.glsl │ │ └── shadow_vert.glsl │ └── ViewFrustumCulling │ └── ViewFrustumCulling.pde ├── lib └── README ├── license.txt ├── natives ├── core.jar ├── gluegen-rt.jar ├── jogl-all.jar ├── linux-aarch64 │ ├── libgluegen_rt.so │ ├── libjogl_desktop.so │ ├── libjogl_mobile.so │ ├── libnativewindow_awt.so │ ├── libnativewindow_drm.so │ ├── libnativewindow_x11.so │ ├── libnewt_drm.so │ └── libnewt_head.so ├── linux-amd64 │ ├── libgluegen_rt.so │ ├── libjogl_desktop.so │ ├── libjogl_mobile.so │ ├── libnativewindow_awt.so │ ├── libnativewindow_drm.so │ ├── libnativewindow_x11.so │ ├── libnewt_drm.so │ └── libnewt_head.so ├── linux-arm │ ├── libgluegen_rt.so │ ├── libjogl_desktop.so │ ├── libjogl_mobile.so │ ├── libnativewindow_awt.so │ ├── libnativewindow_drm.so │ ├── libnativewindow_x11.so │ ├── libnewt_drm.so │ └── libnewt_head.so ├── macos-aarch64 │ ├── libgluegen_rt.dylib │ ├── libjogl_desktop.dylib │ ├── libjogl_mobile.dylib │ ├── libnativewindow_awt.dylib │ ├── libnativewindow_macosx.dylib │ └── libnewt_head.dylib ├── macos-x86_64 │ ├── libgluegen_rt.dylib │ ├── libjogl_desktop.dylib │ ├── libjogl_mobile.dylib │ ├── libnativewindow_awt.dylib │ ├── libnativewindow_macosx.dylib │ └── libnewt_head.dylib └── windows-amd64 │ ├── fenster.exe │ ├── gluegen_rt.dll │ ├── jogl_desktop.dll │ ├── jogl_mobile.dll │ ├── nativewindow_awt.dll │ ├── nativewindow_win32.dll │ └── newt_head.dll ├── resources ├── README.md ├── build.properties ├── build.xml ├── code │ ├── ExampleTaglet.class │ ├── ExampleTaglet.java │ ├── ant-contrib-1.0b3.jar │ └── doc.sh ├── library.properties └── stylesheet.css ├── src └── nub │ ├── core │ ├── Graph.java │ ├── Inertia.java │ ├── Interpolator.java │ ├── MatrixHandler.java │ └── Node.java │ ├── primitives │ ├── Matrix.java │ ├── Quaternion.java │ └── Vector.java │ └── processing │ ├── GLMatrixHandler.java │ └── Scene.java ├── style ├── Proscene.xml └── proscene_eclipse_code_style.xml ├── testing ├── data │ ├── bloom │ │ ├── bloom.glsl │ │ ├── bloomfrag.glsl │ │ ├── bloomvert.glsl │ │ ├── convfrag.glsl │ │ ├── convvert.glsl │ │ └── noise.glsl │ ├── bvh │ │ └── walk-03-sneak-yokoyama.bvh │ ├── ceva │ │ └── sonia.gif │ ├── depth │ │ ├── depth_frag.glsl │ │ ├── depth_linear.glsl │ │ └── depth_nonlinear.glsl │ ├── dof │ │ ├── depth.glsl │ │ └── dof.glsl │ ├── globe │ │ └── world32k.jpg │ ├── interaction │ │ ├── rocket.mtl │ │ ├── rocket.obj │ │ └── rocket.png │ ├── matrix_handler │ │ ├── fragment.glsl │ │ └── vertex.glsl │ ├── objs │ │ ├── Female_low_poly.obj │ │ ├── TropicalFish01.jpg │ │ ├── TropicalFish01.mtl │ │ └── TropicalFish01.obj │ ├── shadow │ │ ├── shadow_frag.glsl │ │ ├── shadow_nub_vert.glsl │ │ └── shadow_vert.glsl │ └── texture │ │ ├── lachoy.jpg │ │ ├── texfrag.glsl │ │ └── texvert.glsl ├── src │ ├── AuxViewers.java │ ├── BasicUse.java │ ├── CajasOrientadas.java │ ├── CevaSonia.java │ ├── CevaSoniaOldStyle.java │ ├── CustomEyeInteraction.java │ ├── CustomNodeInteraction.java │ ├── DOF.java │ ├── DepthMap.java │ ├── FilteredNode.java │ ├── Flock.java │ ├── GraphAPI.java │ ├── Interpolators.java │ ├── Luxo.java │ ├── MiniMap.java │ ├── NodeAPI1.java │ ├── NodeAPI2.java │ ├── Orbit.java │ ├── OrthogonalViewer.java │ ├── PointUnderPixel.java │ ├── SceneBuffers.java │ ├── Superliminal.java │ ├── ViewFrustumCulling.java │ └── VisitExample.java └── testing.iml └── web ├── index.html └── stylesheet.css /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "nub", 3 | "projectOwner": "VisualComputing", 4 | "files": [ 5 | "README.md" 6 | ], 7 | "imageSize": 100, 8 | "commit": true, 9 | "contributors": [ 10 | { 11 | "login": "nakednous", 12 | "name": "Jean Pierre Charalambos", 13 | "avatar_url": "https://avatars2.githubusercontent.com/u/645599?v=4", 14 | "profile": "https://github.com/nakednous", 15 | "contributions": [ 16 | "blog", 17 | "bug", 18 | "code", 19 | "design", 20 | "doc", 21 | "eventOrganizing", 22 | "example", 23 | "financial", 24 | "fundingFinding", 25 | "ideas", 26 | "platform", 27 | "plugin", 28 | "question", 29 | "review", 30 | "talk", 31 | "test", 32 | "tutorial", 33 | "video" 34 | ] 35 | } 36 | ], 37 | "repoType": "github" 38 | } 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ant + build 2 | build 3 | distribution 4 | bin/ 5 | tmp/ 6 | out/ 7 | # idea config 8 | **/.idea/workspace.xml 9 | **/.idea/tasks.xml 10 | # code-oss + eclipse 11 | .lib/ 12 | .settings/ 13 | .project 14 | .classpath 15 | # code-oss + processing 16 | **/.vscode 17 | # nub config 18 | data/config.json 19 | examples/**/config.json 20 | testing/src/processing/**/config.json 21 | -------------------------------------------------------------------------------- /.idea/ant.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/libraries/p5_4x.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/nub.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /assets/FreeSans-13.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/assets/FreeSans-13.vlw -------------------------------------------------------------------------------- /assets/FreeSans-16.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/assets/FreeSans-16.vlw -------------------------------------------------------------------------------- /assets/FreeSans-24.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/assets/FreeSans-24.vlw -------------------------------------------------------------------------------- /assets/FreeSans-36.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/assets/FreeSans-36.vlw -------------------------------------------------------------------------------- /assets/PickingBuffer.frag: -------------------------------------------------------------------------------- 1 | uniform vec3 id; 2 | 3 | void main() { 4 | gl_FragColor = vec4(id, 1.0); 5 | } -------------------------------------------------------------------------------- /data/FreeSans-13.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/data/FreeSans-13.vlw -------------------------------------------------------------------------------- /data/FreeSans-16.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/data/FreeSans-16.vlw -------------------------------------------------------------------------------- /data/FreeSans-24.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/data/FreeSans-24.vlw -------------------------------------------------------------------------------- /data/FreeSans-36.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/data/FreeSans-36.vlw -------------------------------------------------------------------------------- /data/LinePicking.vert: -------------------------------------------------------------------------------- 1 | // took verbatim from here: 2 | // https://github.com/processing/processing/blob/master/core/src/processing/opengl/shaders/LineVert.glsl 3 | 4 | uniform mat4 modelviewMatrix; 5 | uniform mat4 projectionMatrix; 6 | 7 | uniform vec4 viewport; 8 | uniform int perspective; 9 | uniform vec3 scale; 10 | 11 | attribute vec4 position; 12 | attribute vec4 color; 13 | attribute vec4 direction; 14 | 15 | void main() { 16 | vec4 posp = modelviewMatrix * position; 17 | vec4 posq = modelviewMatrix * (position + vec4(direction.xyz, 0)); 18 | 19 | // Moving vertices slightly toward the camera 20 | // to avoid depth-fighting with the fill triangles. 21 | // Discussed here: 22 | // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 23 | posp.xyz = posp.xyz * scale; 24 | posq.xyz = posq.xyz * scale; 25 | 26 | vec4 p = projectionMatrix * posp; 27 | vec4 q = projectionMatrix * posq; 28 | 29 | // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) 30 | // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw 31 | 32 | // prevent division by W by transforming the tangent formula (div by 0 causes 33 | // the line to disappear, see https://github.com/processing/processing/issues/5183) 34 | // t = screen_q - screen_p 35 | // 36 | // tangent is normalized and we don't care which direction it points to (+-) 37 | // t = +- normalize( screen_q - screen_p ) 38 | // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*viewport.zw - (p.xy/p.w+<1,1>)*0.5*viewport.zw ) 39 | // 40 | // extract common factor, <1,1> - <1,1> cancels out 41 | // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * viewport.zw ) 42 | // 43 | // convert to common divisor 44 | // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * viewport.zw ) 45 | // 46 | // remove the common scalar divisor/factor, not needed due to normalize and +- 47 | // (keep viewport - can't remove because it has different components for x and y 48 | // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) 49 | // t = +- normalize( (q.xy*p.w - p.xy*q.w) * viewport.zw ) 50 | 51 | vec2 tangent = (q.xy*p.w - p.xy*q.w) * viewport.zw; 52 | 53 | // don't normalize zero vector (line join triangles and lines perpendicular to the eye plane) 54 | tangent = length(tangent) == 0.0 ? vec2(0.0, 0.0) : normalize(tangent); 55 | 56 | // flip tangent to normal (it's already normalized) 57 | vec2 normal = vec2(-tangent.y, tangent.x); 58 | 59 | float thickness = direction.w; 60 | vec2 offset = normal * thickness; 61 | 62 | // Perspective --- 63 | // convert from world to clip by multiplying with projection scaling factor 64 | // to get the right thickness (see https://github.com/processing/processing/issues/5182) 65 | // invert Y, projections in Processing invert Y 66 | vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; 67 | 68 | // No Perspective --- 69 | // multiply by W (to cancel out division by W later in the pipeline) and 70 | // convert from screen to clip (derived from clip to screen above) 71 | vec2 noPerspScale = p.w / (0.5 * viewport.zw); 72 | 73 | gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); 74 | gl_Position.zw = p.zw; 75 | } -------------------------------------------------------------------------------- /data/Picking.frag: -------------------------------------------------------------------------------- 1 | uniform vec3 id; 2 | 3 | void main() { 4 | gl_FragColor = vec4(id, 1.0); 5 | } -------------------------------------------------------------------------------- /data/PointPicking.vert: -------------------------------------------------------------------------------- 1 | // took verbatim from here: 2 | // https://github.com/processing/processing/blob/master/core/src/processing/opengl/shaders/PointVert.glsl 3 | 4 | uniform mat4 projectionMatrix; 5 | uniform mat4 modelviewMatrix; 6 | 7 | uniform vec4 viewport; 8 | uniform int perspective; 9 | 10 | attribute vec4 position; 11 | attribute vec4 color; 12 | attribute vec2 offset; 13 | 14 | void main() { 15 | vec4 pos = modelviewMatrix * position; 16 | vec4 clip = projectionMatrix * pos; 17 | 18 | // Perspective --- 19 | // convert from world to clip by multiplying with projection scaling factor 20 | // invert Y, projections in Processing invert Y 21 | vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; 22 | 23 | // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) 24 | // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw 25 | 26 | // No Perspective --- 27 | // multiply by W (to cancel out division by W later in the pipeline) and 28 | // convert from screen to clip (derived from clip to screen above) 29 | vec2 noPerspScale = clip.w / (0.5 * viewport.zw); 30 | 31 | gl_Position.xy = clip.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); 32 | gl_Position.zw = clip.zw; 33 | } -------------------------------------------------------------------------------- /examples/basics/AuxiliaryViews/AuxiliaryViews.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Auxiliary Views. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example shows how to setup different views of the same scene. 6 | * It comprises three scenes: the main scene and two auxiliary ones. 7 | * 8 | * Both, the scene objects and their eyes are interactive and controlled 9 | * with the mouse in either scene. Hover over the scene objects to pick 10 | * them. Mouse dragging and clicking defines the interaction of a picked 11 | * object or the eye when no object is currently picked. 12 | * 13 | * Press ' ' to toggle the auxiliary viewer display. 14 | * Press 'f' to fit scene. 15 | * Press 'p' to toggle the focused scene perspective projection. 16 | */ 17 | 18 | import nub.primitives.*; 19 | import nub.core.*; 20 | import nub.processing.*; 21 | 22 | // main and auxiliary scenes 23 | Scene mainScene, sideScene, frontScene; 24 | // focus is either scene and is defined according to the current mouse 25 | // position 26 | Scene focus; 27 | Node[] shapes; 28 | Node[] toruses; 29 | boolean displayAuxiliaryViews = true; 30 | // whilst the main scene is either on-screen or not; the side and the 31 | // front scenes are off-screen. Test both cases here 32 | boolean onScreen = true; 33 | 34 | int w = 1920; 35 | int h = 1080; 36 | 37 | void settings() { 38 | size(w, h, P3D); 39 | } 40 | 41 | void setup() { 42 | mainScene = onScreen ? new Scene(g) : new Scene(createGraphics(w, h, P3D)); 43 | mainScene.setUpVector(Vector.minusK); 44 | mainScene.eye().setPosition(new Vector(150, 150, 50)); 45 | mainScene.lookAt(Vector.zero); 46 | mainScene.eye().tagging = false; 47 | shapes = new Node[15]; 48 | for (int i = 0; i < shapes.length; i++) { 49 | shapes[i] = new Node(boxShape()); 50 | mainScene.randomize(shapes[i]); 51 | } 52 | toruses = new Node[15]; 53 | for (int i = 0; i < toruses.length; i++) { 54 | toruses[i] = new Node(); 55 | toruses[i].enableHint(Node.TORUS); 56 | mainScene.randomize(toruses[i]); 57 | } 58 | // Note that we pass the upper left corner coordinates where the 59 | // scene is to be drawn (see drawing code below) to its constructor. 60 | sideScene = new Scene(createGraphics(w / 2, h / 2, P3D)); 61 | sideScene.setUpVector(Vector.minusJ); 62 | sideScene.eye().setPosition(new Vector(200, 0, 0)); 63 | sideScene.lookAt(Vector.zero); 64 | sideScene.eye().tagging = false; 65 | // idem here 66 | frontScene = new Scene(createGraphics(w / 2, h / 2, P3D)); 67 | frontScene.eye().setPosition(new Vector(0, 200, 0)); 68 | frontScene.lookAt(Vector.zero); 69 | frontScene.eye().tagging = false; 70 | } 71 | 72 | PShape boxShape() { 73 | PShape box = createShape(BOX, 6); 74 | box.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 75 | return box; 76 | } 77 | 78 | void keyPressed() { 79 | if (key == ' ') 80 | displayAuxiliaryViews = !displayAuxiliaryViews; 81 | if (key == 'f') 82 | focus.fit(1000); 83 | if (key == 'p') { 84 | if (focus == null) return; 85 | focus.togglePerspective(); 86 | } 87 | } 88 | 89 | void mouseMoved() { 90 | if (focus == null) return; 91 | focus.tag(); 92 | } 93 | 94 | void mouseDragged() { 95 | if (focus == null) return; 96 | if (mouseButton == LEFT) 97 | focus.spin(); 98 | else if (mouseButton == RIGHT) 99 | focus.shift(); 100 | else 101 | focus.moveForward(focus.mouseDX()); 102 | } 103 | 104 | void mouseWheel(MouseEvent event) { 105 | if (focus == null) return; 106 | focus.zoom(event.getCount() * 20); 107 | } 108 | 109 | void mouseClicked(MouseEvent event) { 110 | if (focus == null) return; 111 | if (event.getCount() == 2) 112 | if (event.getButton() == LEFT) 113 | focus.focus(); 114 | else 115 | focus.align(); 116 | } 117 | 118 | void draw() { 119 | focus = sideScene.hasFocus() ? sideScene : frontScene.hasFocus() ? frontScene : mainScene.hasFocus() ? mainScene : null; 120 | mainScene.display(color(75, 25, 15), true, color(0, 225, 15)); 121 | if (displayAuxiliaryViews) { 122 | sideScene.openContext(); 123 | sideScene.context().background(75, 25, 175, 175); 124 | sideScene.drawAxes(); 125 | sideScene.render(); 126 | sideScene.closeContext(); 127 | sideScene.image(w / 2, 0); 128 | frontScene.openContext(); 129 | frontScene.context().background(175, 200, 20, 175); 130 | frontScene.render(); 131 | frontScene.drawAxes(); 132 | frontScene.closeContext(); 133 | frontScene.image(w / 2, h / 2); 134 | } 135 | } -------------------------------------------------------------------------------- /examples/basics/CajasOrientadas/CajasOrientadas.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Cajas Orientadas. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example illustrates some basic node properties, particularly how to 6 | * orient them. 7 | * 8 | * The sphere and the boxes are interactive. Pick and drag them with the 9 | * right mouse button. Use also the arrow keys to select and move the sphere. 10 | * See how the boxes will always remain oriented towards the sphere. 11 | * 12 | * Press ' ' to change the picking policy. 13 | * Press 'c' to change the bullseye space. 14 | * Press 'd' to change the bullseye shape. 15 | * Press 's' to animate to fit scene. 16 | * Press 'S' to fit scene. 17 | * Press 'u' to toggle interaction between the sphere and the boxes. 18 | */ 19 | 20 | import nub.primitives.*; 21 | import nub.core.*; 22 | import nub.processing.*; 23 | 24 | Scene scene; 25 | Node[] cajas; 26 | Node esfera; 27 | boolean circle; 28 | 29 | void setup() { 30 | size(800, 600, P3D); 31 | // Set the inertia for all interactivity methods to 0.85. Default is 0.8. 32 | Scene.inertia = 0.85; 33 | scene = new Scene(this, 200); 34 | scene.togglePerspective(); 35 | esfera = new Node(esfera(10)); 36 | esfera.setPosition(new Vector(0, 1.4, 0)); 37 | cajas = new Node[15]; 38 | for (int i = 0; i < cajas.length; i++) { 39 | cajas[i] = new Node(caja(random(10, 40), random(10, 40), random(10, 40))); 40 | cajas[i].togglePicking(Node.SHAPE | Node.AXES); 41 | cajas[i].enableHint(Node.AXES | Node.BULLSEYE); 42 | scene.addBehavior(cajas[i], (Node node) -> { 43 | Vector to = Vector.subtract(esfera.position(), node.position()); 44 | node.setOrientation(Quaternion.from(Vector.plusJ, to)); 45 | }); 46 | scene.randomize(cajas[i]); 47 | } 48 | scene.tag("keyboard", esfera); 49 | } 50 | 51 | PShape caja(float w, float h, float d) { 52 | PShape caja = createShape(BOX, w, h, d); 53 | caja.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 54 | caja.setStroke(false); 55 | return caja; 56 | } 57 | 58 | PShape esfera(float r) { 59 | PShape esfera = createShape(SPHERE, r); 60 | esfera.setStroke(false); 61 | esfera.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 62 | return esfera; 63 | } 64 | 65 | void draw() { 66 | background(0); 67 | scene.render(); 68 | } 69 | 70 | void mouseClicked() { 71 | scene.focus(); 72 | } 73 | 74 | void mouseMoved() { 75 | scene.tag(); 76 | } 77 | 78 | void mouseDragged() { 79 | if (scene.node("keyboard") != null) { 80 | scene.shift("keyboard"); 81 | } 82 | else { 83 | if (mouseButton == LEFT) 84 | scene.spin(); 85 | else if (mouseButton == RIGHT) 86 | scene.shift(); 87 | else 88 | scene.zoom(mouseX - pmouseX); 89 | } 90 | } 91 | 92 | void mouseWheel(MouseEvent event) { 93 | scene.moveForward(event.getCount() * 20); 94 | } 95 | 96 | void keyPressed() { 97 | if (key == ' ') { 98 | for (Node caja : cajas) { 99 | caja.togglePicking(Node.BULLSEYE | Node.SHAPE | Node.AXES); 100 | caja.toggleHint(Node.BULLSEYE); 101 | } 102 | } 103 | if (key == 'c') { 104 | for (Node caja : cajas) 105 | if (caja.bullsEyeSize() < 1) 106 | caja.setBullsEyeSize(caja.bullsEyeSize() * 200); 107 | else 108 | caja.setBullsEyeSize(caja.bullsEyeSize() / 200); 109 | } 110 | if (key == 'd') { 111 | circle = !circle; 112 | for (Node caja : cajas) 113 | caja.configHint(Node.BULLSEYE, circle ? 114 | Node.BullsEyeShape.CIRCLE : 115 | Node.BullsEyeShape.SQUARE); 116 | } 117 | if (key == 'e') { 118 | scene.togglePerspective(); 119 | } 120 | if (key == 's') { 121 | scene.fit(1000); 122 | } 123 | if (key == 'S') { 124 | scene.fit(); 125 | } 126 | if (key == 'u') { 127 | if (scene.isTagValid("keyboard")) 128 | scene.removeTag("keyboard"); 129 | else 130 | scene.tag("keyboard", esfera); 131 | } 132 | if (key == CODED) { 133 | if (keyCode == UP) 134 | scene.shift("keyboard", 0, -10, 0); 135 | else if (keyCode == DOWN) 136 | scene.shift("keyboard", 0, 10, 0); 137 | else if (keyCode == LEFT) 138 | scene.shift("keyboard", -10, 0, 0); 139 | else if (keyCode == RIGHT) 140 | scene.shift("keyboard", 10, 0, 0); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /examples/basics/Eye/Eye.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Eye. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example illustrates how to setup and use an scene eye. 6 | * 7 | * Press '1' to add keyframes to the eye. 8 | * Press '2' to animate the eye along the keyframes. 9 | * Press '3' to remove all keyframes. 10 | */ 11 | 12 | import nub.processing.*; 13 | 14 | Scene scene; 15 | 16 | void setup() { 17 | size(800, 600, P3D); 18 | scene = new Scene(this, 400); 19 | } 20 | 21 | void draw() { 22 | background(0); 23 | stroke(0, 255, 0); 24 | strokeWeight(1); 25 | scene.drawGrid(); 26 | strokeWeight(8); 27 | scene.drawAxes(); 28 | lights(); 29 | fill(255, 0, 0); 30 | rotateX(QUARTER_PI); 31 | stroke(255, 255, 0); 32 | strokeWeight(3); 33 | box(200); 34 | push(); 35 | translate(0, 0, 180); 36 | rotateY(QUARTER_PI); 37 | fill(0, 0, 255); 38 | scene.drawTorusSolenoid(); 39 | pop(); 40 | } 41 | 42 | void mouseDragged() { 43 | if (mouseButton == LEFT) { 44 | scene.spin(); 45 | } 46 | else if (mouseButton == RIGHT) { 47 | scene.shift(); 48 | } 49 | else { 50 | scene.moveForward(scene.mouseDX()); 51 | } 52 | } 53 | 54 | void keyPressed() { 55 | if (key == '1') { 56 | scene.eye().addKeyFrame(); 57 | } 58 | if (key == '2') { 59 | scene.eye().animate(); 60 | } 61 | if (key == '3') { 62 | scene.eye().removeKeyFrames(); 63 | } 64 | } -------------------------------------------------------------------------------- /examples/basics/KeyFrames/KeyFrames.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * KeyFrames. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example introduces node keyframes. 6 | * 7 | * Press ' ' to toggle the shape end eye keyframes hint. 8 | * Press 's' to toggle the shape animation. 9 | * Press '+' to speed up the shape animation. 10 | * Press '-' to speed down the shape animation. 11 | * Press 'f' to interpolate the eye to fit the scene bounding volume. 12 | * Press '1' to add key-frame to the eye path. 13 | * Press 'a' to play the eye path. 14 | * Press 'b' to remove the eye path. 15 | */ 16 | 17 | import nub.primitives.*; 18 | import nub.core.*; 19 | import nub.processing.*; 20 | 21 | Scene scene; 22 | Node shape; 23 | 24 | // Choose P3D or P2D 25 | String renderer = P3D; 26 | float speed = 1; 27 | 28 | void setup() { 29 | size(1000, 700, renderer); 30 | scene = new Scene(this, 150); 31 | PShape pshape; 32 | if (scene.is2D()) { 33 | rectMode(CENTER); 34 | pshape = createShape(RECT, 0, 0, 100, 100); 35 | } else { 36 | pshape = createShape(BOX, 30); 37 | } 38 | pshape.setFill(color(0, 255, 255, 125)); 39 | shape = new Node(pshape); 40 | shape.setMinMaxScalingFilter(0.8, 1.2); 41 | shape.setHUD(this::hud); 42 | shape.enableHint(Node.AXES); 43 | shape.enableHint(Node.BULLSEYE); 44 | shape.configHint(Node.BULLSEYE, color(255, 0, 0)); 45 | shape.setBullsEyeSize(50); 46 | shape.enableHint(Node.KEYFRAMES, Node.AXES, 2, color(0, 255, 0), 6); 47 | shape.setAnimationRecurrence(true); 48 | // Create an initial shape interpolator path 49 | for (int i = 0; i < random(4, 10); i++) { 50 | scene.randomize(shape); 51 | shape.addKeyFrame(Node.AXES | Node.SHAPE | Node.HUD, i % 2 == 1 ? 1000 : 4000); 52 | } 53 | shape.resetScalingFilter(); 54 | shape.animate(); 55 | scene.eye().enableHint(Node.KEYFRAMES); 56 | } 57 | 58 | void hud(PGraphics pg) { 59 | pg.pushStyle(); 60 | pg.rectMode(CENTER); 61 | pg.fill(255, 0, 255, 125); 62 | pg.stroke(0,0,255); 63 | pg.strokeWeight(3); 64 | pg.rect(0, 0, 80, 50); 65 | pg.popStyle(); 66 | } 67 | 68 | void draw() { 69 | background(125); 70 | scene.render(); 71 | stroke(255, 255, 0); 72 | scene.drawGrid(); 73 | } 74 | 75 | void mouseMoved() { 76 | scene.updateTag(); 77 | } 78 | 79 | void mouseDragged() { 80 | if (mouseButton == LEFT) 81 | scene.spin(); 82 | else if (mouseButton == RIGHT) 83 | scene.shift(); 84 | else 85 | scene.zoom(mouseX - pmouseX); 86 | } 87 | 88 | void mouseWheel(MouseEvent event) { 89 | if (scene.is3D()) 90 | scene.moveForward(event.getCount() * 20); 91 | else 92 | scene.zoom(event.getCount() * 20); 93 | } 94 | 95 | void keyPressed() { 96 | if (key == ' ') { 97 | shape.toggleHint(Node.KEYFRAMES); 98 | scene.eye().toggleHint(Node.KEYFRAMES); 99 | } 100 | if (key == 's') 101 | shape.toggleAnimation(); 102 | if (key == '-' || key == '+') { 103 | speed += key == '+' ? 0.25f : -0.25f; 104 | shape.animate(speed); 105 | } 106 | if (key == '1') 107 | scene.eye().addKeyFrame(Node.CAMERA | Node.BULLSEYE, 1000); 108 | if (key == 'a') 109 | scene.eye().toggleAnimation(); 110 | if (key == 'b') 111 | scene.eye().removeKeyFrames(); 112 | if (key == 'f') 113 | scene.fit(1000); 114 | } 115 | -------------------------------------------------------------------------------- /examples/basics/Luxo/Luxo.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Luxo. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example displays a famous luxo lamp (Pixar) that can be interactively 6 | * manipulated with the mouse. It combines node shapes, filters and picking. 7 | * 8 | * Hover over lamp elements to pick them, and then drag them with the mouse. 9 | */ 10 | 11 | import nub.primitives.*; 12 | import nub.core.*; 13 | import nub.processing.*; 14 | 15 | Scene scene; 16 | Node floor, base, arm, forarm, shade; 17 | 18 | void setup() { 19 | size(1000, 700, P3D); 20 | scene = new Scene(this); 21 | base = new Node(this::base); 22 | base.setTranslationPlaneFilter(Vector.plusK); 23 | base.setRotationAxisFilter(Vector.plusK); 24 | arm = new Node(base, this::limb); 25 | arm.setPosition(0, 0, 8); 26 | arm.setOrientation(Quaternion.from(Vector.plusI, 0.6)); 27 | arm.setRotationAxisFilter(Vector.plusI); 28 | forarm = new Node(arm, this::limb); 29 | forarm.setPosition(0, 0, 50); 30 | forarm.setOrientation(Quaternion.from(Vector.plusI, -2)); 31 | forarm.setRotationAxisFilter(Vector.plusI); 32 | shade = new Node(forarm, this::shade); 33 | shade.setPosition(0, 0, 50); 34 | shade.setOrientation(Quaternion.from(new Vector(1, -0.3f, 0), -1.7)); 35 | // for the lights to work the floor node should be the last to be added 36 | floor = new Node(this::floor); 37 | floor.tagging = false; 38 | } 39 | 40 | void cone(PGraphics pg, float zMin, float zMax, float r1, float r2, int nbSub) { 41 | pg.pushStyle(); 42 | pg.noStroke(); 43 | pg.translate(0, 0, zMin); 44 | Scene.drawCone(pg, nbSub, 0, 0, r1, r2, zMax - zMin); 45 | pg.translate(0, 0, -zMin); 46 | pg.popStyle(); 47 | } 48 | 49 | void base(PGraphics pg) { 50 | pg.pushStyle(); 51 | pg.fill(0, 0, 255); 52 | cone(pg, 0, 3, 15, 15, 30); 53 | cone(pg, 3, 5, 15, 13, 30); 54 | cone(pg, 5, 7, 13, 1, 30); 55 | cone(pg, 7, 9, 1, 1, 10); 56 | pg.popStyle(); 57 | } 58 | 59 | void limb(PGraphics pg) { 60 | pg.pushStyle(); 61 | pg.pushMatrix(); 62 | pg.rotate(HALF_PI, 0, 1, 0); 63 | cone(pg, -5, 5, 2, 2, 20); 64 | pg.popMatrix(); 65 | pg.translate(2, 0, 0); 66 | cone(pg, 0, 50, 1, 1, 10); 67 | pg.translate(-4, 0, 0); 68 | cone(pg, 0, 50, 1, 1, 10); 69 | pg.translate(2, 0, 0); 70 | pg.popStyle(); 71 | } 72 | 73 | void shade(PGraphics pg) { 74 | pg.pushStyle(); 75 | pg.fill(0, 255, 255); 76 | cone(pg, -2, 6, 4, 4, 30); 77 | cone(pg, 6, 15, 4, 17, 30); 78 | cone(pg, 15, 17, 17, 17, 30); 79 | pg.spotLight(155, 255, 255, 0, 0, 0, 0, 0, 1, THIRD_PI, 1); 80 | pg.popStyle(); 81 | } 82 | 83 | void floor(PGraphics pg) { 84 | pg.pushStyle(); 85 | pg.noStroke(); 86 | pg.fill(120, 120, 120); 87 | float nbPatches = 100; 88 | pg.normal(0, 0, 1); 89 | for (int j = 0; j < nbPatches; ++j) { 90 | pg.beginShape(QUAD_STRIP); 91 | for (int i = 0; i <= nbPatches; ++i) { 92 | pg.vertex((200 * (float) i / nbPatches - 100), (200 * j / nbPatches - 100)); 93 | pg.vertex((200 * (float) i / nbPatches - 100), (200 * (float) (j + 1) / nbPatches - 100)); 94 | } 95 | pg.endShape(); 96 | } 97 | pg.popStyle(); 98 | } 99 | 100 | void draw() { 101 | background(0); 102 | lights(); 103 | scene.render(); 104 | } 105 | 106 | void mouseMoved() { 107 | scene.tag(); 108 | } 109 | 110 | void mouseDragged() { 111 | if (mouseButton == LEFT) 112 | scene.spin(); 113 | else if (mouseButton == RIGHT) { 114 | if (scene.node() == base || scene.node() == null) 115 | scene.shift(); 116 | } 117 | else 118 | scene.zoom(mouseX - pmouseX); 119 | } 120 | 121 | void mouseWheel(MouseEvent event) { 122 | scene.moveForward(event.getCount() * 20); 123 | } 124 | -------------------------------------------------------------------------------- /examples/basics/SceneBuffers/SceneBuffers.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Scene Buffers. 3 | * by Sebastian Chaparro & Jean Pierre Charalambos. 4 | * 5 | * This example displays the scene front and back buffers. 6 | * 7 | * The front buffer is filled with some scene objects. The 8 | * back buffer is used to pick them. Calling displayBackBuffer 9 | * is useful for debugging. 10 | * 11 | * Press 'a' to toggle the node axes hint. 12 | */ 13 | 14 | import nub.primitives.*; 15 | import nub.core.*; 16 | import nub.processing.*; 17 | 18 | Scene scene; 19 | Node cajas, bolas; 20 | Node[] shapes; 21 | 22 | //Choose P2D or P3D 23 | String renderer = P3D; 24 | int w = 1200; 25 | int h = 1200; 26 | 27 | void settings() { 28 | size(w, h, renderer); 29 | } 30 | 31 | void setup() { 32 | rectMode(CENTER); 33 | scene = new Scene(createGraphics(w, h /2, renderer), max(w, h)); 34 | cajas = new Node(); 35 | bolas = new Node(); 36 | shapes = new Node[100]; 37 | for (int i = 0; i < shapes.length; i++) { 38 | if (i%2==0) { 39 | shapes[i] = new Node(cajas, caja()); 40 | } 41 | else { 42 | shapes[i] = new Node(bolas, bola()); 43 | } 44 | scene.randomize(shapes[i]); 45 | shapes[i].enableHint(Node.AXES); 46 | } 47 | } 48 | 49 | void draw() { 50 | // (un)comment as you wish 51 | // 1. Fill in and display front-buffer 52 | // 1a. Display both cajas and bolas 53 | //scene.display(color(10, 50, 25)); 54 | // 1b. Display either cajas or bolas, or both 55 | //scene.display(color(0), bolas); 56 | //scene.display(cajas); 57 | // 1c. Display either cajas or bolas, or both 58 | scene.openContext(); 59 | scene.context().background(color(10, 50, 25)); 60 | scene.drawAxes(); 61 | scene.render(cajas); 62 | scene.render(bolas); 63 | scene.closeContext(); 64 | scene.image(); 65 | // 2. Display back buffer 66 | scene.displayBackBuffer(0, h / 2); 67 | } 68 | 69 | void mouseMoved() { 70 | scene.tag(); 71 | } 72 | 73 | void mouseDragged() { 74 | if (mouseButton == LEFT) 75 | scene.spin(); 76 | else if (mouseButton == RIGHT) 77 | scene.shift(); 78 | else 79 | scene.zoom(mouseX - pmouseX); 80 | } 81 | 82 | void mouseWheel(MouseEvent event) { 83 | if (scene.is3D()) 84 | scene.moveForward(event.getCount() * 30); 85 | else 86 | scene.zoom(event.getCount() * 20); 87 | } 88 | 89 | void keyPressed() { 90 | if (key == 'a') { 91 | for (int i = 0; i < shapes.length; i++) 92 | shapes[i].toggleHint(Node.AXES); 93 | } 94 | } 95 | 96 | PShape caja() { 97 | PShape caja = scene.is3D() ? createShape(BOX, random(60, 100)) : createShape(RECT, 0, 0, random(60, 100), random(60, 100)); 98 | caja.setStrokeWeight(3); 99 | caja.setStroke(color(random(0, 255), random(0, 255), random(0, 255))); 100 | caja.setFill(color(random(0, 255), random(0, 255), random(0, 255), random(0, 255))); 101 | return caja; 102 | } 103 | 104 | PShape bola() { 105 | PShape bola = scene.is3D() ? createShape(SPHERE, random(60, 100)) : createShape(ELLIPSE, 0, 0, random(60, 100), random(60, 100)); 106 | bola.setStroke(color(random(0, 255), random(0, 255), random(0, 255))); 107 | bola.setFill(color(random(0, 255), random(0, 255), random(0, 255), random(0, 255))); 108 | return bola; 109 | } -------------------------------------------------------------------------------- /examples/basics/SpaceNavigator/SpaceNavigator.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Space Navigator 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example shows how to control your scene shapes using a Space Navigator 6 | * (3D mouse), with 6 degrees-of-freedom (DOFs). It requires the GameControlPlus 7 | * library and a Space Navigator and it has been tested only under Linux. 8 | */ 9 | 10 | import nub.primitives.*; 11 | import nub.core.*; 12 | import nub.processing.*; 13 | 14 | import org.gamecontrolplus.*; 15 | import net.java.games.input.*; 16 | 17 | ControlIO control; 18 | ControlDevice device; // my SpaceNavigator 19 | ControlSlider snXPos; // Positions 20 | ControlSlider snYPos; 21 | ControlSlider snZPos; 22 | ControlSlider snXRot; // Rotations 23 | ControlSlider snYRot; 24 | ControlSlider snZRot; 25 | ControlButton button1; // Buttons 26 | ControlButton button2; 27 | 28 | // nub stuff: 29 | Scene scene; 30 | boolean snPicking; 31 | 32 | void setup() { 33 | size(1600, 800, P3D); 34 | openSpaceNavigator(); 35 | scene = new Scene(this, 1500); 36 | Node[] shapes = new Node[50]; 37 | for (int i = 0; i < shapes.length; i++) { 38 | tint(random(0,255), random(0,255), random(0,255), random(150,255)); 39 | shapes[i] = new Node(loadShape("rocket.obj")); 40 | scene.randomize(shapes[i]); 41 | } 42 | smooth(); 43 | } 44 | 45 | void draw() { 46 | background(0); 47 | scene.render(); 48 | scene.drawAxes(); 49 | if (snPicking) 50 | spaceNavigatorPicking(); 51 | else 52 | spaceNavigatorInteraction(); 53 | } 54 | 55 | void spaceNavigatorPicking() { 56 | float x = map(snXPos.getValue(), -0.8, 0.8, 0, width); 57 | float y = map(snYPos.getValue(), -0.8, 0.8, 0, height); 58 | // update the space navigator tagged node: 59 | scene.tag("SPCNAV", int(x), int(y)); 60 | // draw picking visual hint 61 | pushStyle(); 62 | strokeWeight(3); 63 | stroke(0, 255, 0); 64 | scene.drawCross(x, y, 30); 65 | popStyle(); 66 | } 67 | 68 | void spaceNavigatorInteraction() { 69 | // translate(x, y, z) expects params in screen-space 70 | // which has dimensions width * height * 1 71 | if (scene.node("SPCNAV") != null) { 72 | scene.shift("SPCNAV", 20 * snXPos.getValue(), 20 * snYPos.getValue(), snZPos.getValue() / 50); 73 | scene.turn("SPCNAV", -snXRot.getValue() * 20 * PI / width, snYRot.getValue() * 20 * PI / width, snZRot.getValue() * 20 * PI / width); 74 | } 75 | else { 76 | scene.shift(20 * snXPos.getValue(), 20 * snYPos.getValue(), snZPos.getValue() / 50); 77 | scene.turn(-snXRot.getValue() * 20 * PI / width, snYRot.getValue() * 20 * PI / width, snZRot.getValue() * 20 * PI / width); 78 | } 79 | } 80 | 81 | void mouseMoved() { 82 | scene.tag(); 83 | } 84 | 85 | void mouseDragged() { 86 | if (mouseButton == LEFT) 87 | scene.spin(); 88 | else if (mouseButton == RIGHT) 89 | scene.shift(); 90 | else 91 | scene.zoom(scene.mouseDX()); 92 | } 93 | 94 | void mouseWheel(MouseEvent event) { 95 | scene.moveForward(event.getCount() * 20); 96 | } 97 | 98 | void keyPressed() { 99 | if (key == ' ') 100 | snPicking = !snPicking; 101 | } 102 | 103 | void openSpaceNavigator() { 104 | println(System.getProperty("os.name")); 105 | control = ControlIO.getInstance(this); 106 | String os = System.getProperty("os.name").toLowerCase(); 107 | if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) 108 | device = control.getDevice("3Dconnexion SpaceNavigator");// magic name for linux 109 | else 110 | device = control.getDevice("SpaceNavigator");//magic name, for windows 111 | if (device == null) { 112 | println("No suitable device configured"); 113 | System.exit(-1); // End the program NOW! 114 | } 115 | //device.setTolerance(5); 116 | snXPos = device.getSlider(0); 117 | snYPos = device.getSlider(1); 118 | snZPos = device.getSlider(2); 119 | snXRot = device.getSlider(3); 120 | snYRot = device.getSlider(4); 121 | snZRot = device.getSlider(5); 122 | //button1 = device.getButton(0); 123 | //button2 = device.getButton(1); 124 | } 125 | -------------------------------------------------------------------------------- /examples/basics/SpaceNavigator/data/rocket.mtl: -------------------------------------------------------------------------------- 1 | newmtl Default 2 | illum 2 3 | Ka 0.698039 0.698039 0.698039 4 | Kd 0.698039 0.698039 0.698039 5 | Ks 0.710000 0.710000 0.710000 6 | Ns 76.109253 7 | map_Kd rocket.png 8 | 9 | -------------------------------------------------------------------------------- /examples/basics/SpaceNavigator/data/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/examples/basics/SpaceNavigator/data/rocket.png -------------------------------------------------------------------------------- /examples/basics/SpaceNavigator/data/world32k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/examples/basics/SpaceNavigator/data/world32k.jpg -------------------------------------------------------------------------------- /examples/demos/CevaSonia/data/sonia.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/examples/demos/CevaSonia/data/sonia.gif -------------------------------------------------------------------------------- /examples/demos/CustomEyeInteraction/data/world32k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/examples/demos/CustomEyeInteraction/data/world32k.jpg -------------------------------------------------------------------------------- /examples/demos/CustomNodeInteraction/CustomNodeInteraction.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Node Interaction. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example illustrates how to customize the toruses behaviors 6 | * by overriding the interact(Object... gesture) method and 7 | * sending gesture data to the node with the scene 8 | * interact(Object... gesture) method. 9 | * 10 | * The toruses color and number of faces are controlled with the 11 | * keys and the mouse. To pick a torus press the [0..9] keys 12 | * or double-click on it; press other key or double-click on the 13 | * the background to reset your picking selection. Once a torus 14 | * is picked try the key arrows, the mouse wheel or a single 15 | * mouse click, to control its color and number of faces. 16 | */ 17 | 18 | import nub.primitives.*; 19 | import nub.core.*; 20 | import nub.processing.*; 21 | 22 | Scene scene; 23 | Torus[] shapes; 24 | PFont font36; 25 | int totalShapes; 26 | 27 | //Choose P2D or P3D 28 | String renderer = P3D; 29 | 30 | void settings() { 31 | size(1200, 700, renderer); 32 | } 33 | 34 | void setup() { 35 | font36 = loadFont("FreeSans-36.vlw"); 36 | scene = new Scene(this); 37 | shapes = new Torus[10]; 38 | for (int i = 0; i < shapes.length; i++) { 39 | shapes[i] = new Torus(); 40 | } 41 | } 42 | 43 | void draw() { 44 | background(0); 45 | scene.render(); 46 | scene.drawAxes(); 47 | } 48 | 49 | void keyPressed() { 50 | int value = Character.getNumericValue(key); 51 | if (value >= 0 && value < 10) 52 | scene.tag("key", shapes[value].node); 53 | if (key == ' ') 54 | scene.removeTag("key"); 55 | if (key == CODED) 56 | if (keyCode == UP) 57 | scene.shift("key", 0, -10, 0); 58 | else if (keyCode == DOWN) 59 | scene.shift("key", 0, 10, 0); 60 | else if (keyCode == LEFT) 61 | scene.interact("key", "menos"); 62 | else if (keyCode == RIGHT) 63 | scene.interact("key", "mas"); 64 | } 65 | 66 | void mouseDragged() { 67 | if (scene.node("key") != null) { 68 | if (mouseButton == LEFT) 69 | scene.spin("key"); 70 | else if (mouseButton == CENTER) 71 | scene.zoom("key", scene.mouseDX()); 72 | else 73 | scene.shift("key"); 74 | } 75 | else { 76 | scene.spin(); 77 | } 78 | } 79 | 80 | void mouseWheel(MouseEvent event) { 81 | scene.interact("key", event.getCount()); 82 | } 83 | 84 | void mouseClicked(MouseEvent event) { 85 | if (event.getCount() == 1) 86 | scene.interact("key"); 87 | if (event.getCount() == 2) 88 | scene.tag("key"); 89 | } 90 | -------------------------------------------------------------------------------- /examples/demos/CustomNodeInteraction/Torus.pde: -------------------------------------------------------------------------------- 1 | class Torus { 2 | int id = totalShapes++, faces = randomFaces(), colour = randomColor(); 3 | Node node; 4 | 5 | Torus() { 6 | node = new Node(); 7 | node.enableHint(Node.TORUS, colour, faces); 8 | node.setInteraction(this::interact); 9 | node.setHUD(this::hud); 10 | scene.randomize(node); 11 | } 12 | 13 | void hud(PGraphics pg) { 14 | pg.fill(node.isTagged(scene) ? 0 : 255, node.isTagged(scene) ? 255 : 0, node.isTagged(scene) ? 0 : 255); 15 | pg.textFont(font36); 16 | pg.text(id, 0, 0); 17 | } 18 | 19 | void interact(Object[] gesture) { 20 | if (gesture.length == 0){ 21 | colour = randomColor(); 22 | node.configHint(Node.TORUS, colour, faces); 23 | } 24 | if (gesture.length == 1) { 25 | if (gesture[0] instanceof String) { 26 | if (((String) gesture[0]).matches("mas")) 27 | faces++; 28 | else if (((String) gesture[0]).matches("menos")) 29 | if (faces > 2) 30 | faces--; 31 | } else if (gesture[0] instanceof Integer) { 32 | int delta = (Integer) gesture[0]; 33 | if (faces + delta > 1) 34 | faces = faces + delta; 35 | } 36 | node.configHint(Node.TORUS, colour, faces); 37 | } 38 | } 39 | 40 | int randomColor() { 41 | return color(random(255), random(255), random(255), random(125, 255)); 42 | } 43 | 44 | int randomFaces() { 45 | return (int) random(3, 15); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/demos/DepthMap/DepthMap.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Depth Map. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example shows how to generate and display a depth map from a light point-of-view. 6 | * 7 | * Refer also to the shadow mapping demo. 8 | * 9 | * Press shift and pick (mouse move) a box to define it as the light source. 10 | * Press shift and scroll (mouse wheel) the light source to change the shadow map zFar plane. 11 | * Press ' ' to change the shadow map volume (ORTHOGRAPHIC / PERSPECTIVE). 12 | * Press 'p' to toggle the scene perspective. 13 | */ 14 | 15 | import nub.primitives.*; 16 | import nub.core.*; 17 | import nub.processing.*; 18 | 19 | Scene.Type shadowMapType = Scene.Type.ORTHOGRAPHIC; 20 | Scene scene, shadowMapScene; 21 | Node[] shapes; 22 | PGraphics shadowMap; 23 | PShader depthShader; 24 | int w = 1200; 25 | int h = 1200; 26 | 27 | void settings() { 28 | size(w, h, P3D); 29 | } 30 | 31 | void setup() { 32 | // main scene 33 | scene = new Scene(this, max(w, h)); 34 | // shapes 35 | shapes = new Node[20]; 36 | for (int i = 0; i < shapes.length; i++) { 37 | shapes[i] = new Node((PGraphics pg) -> { 38 | pg.pushStyle(); 39 | if (pg == shadowMap) 40 | pg.noStroke(); 41 | else { 42 | pg.strokeWeight(3); 43 | pg.stroke(0, 255, 255); 44 | } 45 | pg.fill(255, 0, 0); 46 | pg.box(80); 47 | pg.popStyle(); 48 | }); 49 | shapes[i].setHighlight(0); 50 | scene.randomize(shapes[i]); 51 | } 52 | // light 53 | scene.tag("light", shapes[(int) random(0, shapes.length - 1)]); 54 | scene.node("light").toggleHint(Node.SHAPE | Node.BOUNDS | Node.AXES); 55 | scene.node("light").setOrientation(Quaternion.from(Vector.plusK, scene.node("light").position())); 56 | // shadow map 57 | shadowMap = createGraphics(w / 2, h / 2, P3D); 58 | // shadow map scene 59 | shadowMapScene = new Scene(shadowMap, scene.node("light")); 60 | shadowMapScene.setZNear(() -> 50f); 61 | shadowMapScene.setZFar(() -> 700f); 62 | shadowMapScene.togglePerspective(); 63 | shadowMapScene.picking = false; 64 | depthShader = loadShader("depth.glsl"); 65 | depthShader.set("near", shadowMapScene.zNear()); 66 | depthShader.set("far", shadowMapScene.zFar()); 67 | shadowMap.shader(depthShader); 68 | } 69 | 70 | void draw() { 71 | // 1. Fill in and display front-buffer 72 | background(75, 25, 15); 73 | scene.render(); 74 | // 2. Fill in shadow map using the light point of view 75 | if (scene.isTagValid("light")) { 76 | shadowMapScene.display(color(140, 160, 125), w / 2, h / 2); 77 | } 78 | } 79 | 80 | void mouseMoved(MouseEvent event) { 81 | if (event.isShiftDown()) { 82 | if (scene.isTagValid("light")) { 83 | scene.node("light").toggleHint(Node.SHAPE | Node.AXES | Node.BOUNDS); 84 | } 85 | // no calling tag since we need to immediately update the tagged node 86 | scene.updateTag("light"); 87 | if (scene.isTagValid("light")) { 88 | shadowMapScene.setEye(scene.node("light")); 89 | scene.node("light").toggleHint(Node.SHAPE | Node.AXES | Node.BOUNDS); 90 | } 91 | } else 92 | scene.tag(); 93 | } 94 | 95 | void mouseDragged() { 96 | if (mouseButton == LEFT) 97 | scene.spin(); 98 | else if (mouseButton == RIGHT) 99 | scene.shift(); 100 | else 101 | scene.moveForward(mouseX - pmouseX); 102 | } 103 | 104 | void mouseWheel(MouseEvent event) { 105 | if (event.isShiftDown() && scene.isTagValid("light")) { 106 | float zFar = shadowMapScene.zFar(); 107 | shadowMapScene.setZFar(() -> zFar + event.getCount() * 20f); 108 | depthShader.set("far", shadowMapScene.zFar()); 109 | } else 110 | scene.zoom(event.getCount() * 20); 111 | } 112 | 113 | void keyPressed() { 114 | if (key == ' ' && scene.isTagValid("light")) { 115 | shadowMapScene.togglePerspective(); 116 | } 117 | if (key == 'p') 118 | scene.togglePerspective(); 119 | } -------------------------------------------------------------------------------- /examples/demos/DepthMap/data/depth.glsl: -------------------------------------------------------------------------------- 1 | // The fragment eye depth is obtained by solving z_e in terms z_n from here: 2 | // http://visualcomputing.github.io/Transformations/#/6/14 and: 3 | // http://visualcomputing.github.io/Transformations/#/6/15 4 | // yielding to: z_e = (2 * near * far) / (z_n * (far - near) - far - near) (eq1) 5 | 6 | uniform float near; 7 | uniform float far; 8 | 9 | // remapping of a value among 2 ranges: http://visualcomputing.github.io/Transformations/#/7/1 10 | // same as: https://processing.org/reference/map_.html 11 | float map(float value, float start1, float stop1, float start2, float stop2) { 12 | return start2 + (value - start1) * (stop2 - start2) / (stop1 - start1); 13 | } 14 | 15 | void main() { 16 | // z_n is obtained by remapping gl_FragCoord.z from [0..1] to [-1..1] 17 | float z_n = map(gl_FragCoord.z, 0, 1, -1, 1); 18 | // eq 1 19 | float z_e = (2 * near * far) / (z_n * (far - near) - far - near); 20 | // the normalized eye depth is obtained by remapping z_e from [-near..-far] to [0..1] 21 | float depth = map(z_e, -near, -far, 0, 1); 22 | // render the depth as a grey scale color 23 | gl_FragColor = vec4(vec3(depth), 1); 24 | } -------------------------------------------------------------------------------- /examples/demos/FlockOfBoids/Boid.pde: -------------------------------------------------------------------------------- 1 | class Boid { 2 | // Node 3 | Node node; 4 | // fields 5 | Vector velocity, acceleration, alignment, cohesion, separation; // position, velocity, and acceleration in 6 | // a vector datatype 7 | final float neighborhoodRadius = 100; // radius in which it looks for fellow boids 8 | final float maxSpeed = 4; // maximum magnitude for the velocity vector 9 | final float maxSteerForce = 0.1f; // maximum magnitude of the steering vector 10 | final float sc = 3; // scale factor for the render of the boid 11 | 12 | Boid(Vector inPos) { 13 | node = new Node(inPos); 14 | node.setShape(this::display); 15 | startAnimation(); 16 | velocity = Vector.random(); 17 | acceleration = new Vector(); 18 | } 19 | 20 | void startAnimation() { 21 | node.setBehavior(scene, this::behavior); 22 | } 23 | 24 | void stopAnimation() { 25 | scene.resetBehavior(node); 26 | } 27 | 28 | void display(PGraphics pg) { 29 | pg.pushStyle(); 30 | // uncomment to draw boid axes 31 | //Scene.drawAxes(pg, 10); 32 | pg.strokeWeight(2); 33 | pg.stroke(color(40, 255, 40)); 34 | pg.fill(color(0, 255, 0, 125)); 35 | // highlight boids under the mouse 36 | if (scene.node("mouseMoved") == node) { 37 | pg.stroke(color(0, 0, 255)); 38 | pg.fill(color(0, 0, 255)); 39 | } 40 | // highlight avatar 41 | if (node == avatar) { 42 | pg.stroke(color(255, 0, 0)); 43 | pg.fill(color(255, 0, 0)); 44 | } 45 | //draw boid 46 | pg.beginShape(TRIANGLES); 47 | pg.vertex(3 * sc, 0, 0); 48 | pg.vertex(-3 * sc, 2 * sc, 0); 49 | pg.vertex(-3 * sc, -2 * sc, 0); 50 | pg.vertex(3 * sc, 0, 0); 51 | pg.vertex(-3 * sc, 2 * sc, 0); 52 | pg.vertex(-3 * sc, 0, 2 * sc); 53 | pg.vertex(3 * sc, 0, 0); 54 | pg.vertex(-3 * sc, 0, 2 * sc); 55 | pg.vertex(-3 * sc, -2 * sc, 0); 56 | pg.vertex(-3 * sc, 0, 2 * sc); 57 | pg.vertex(-3 * sc, 2 * sc, 0); 58 | pg.vertex(-3 * sc, -2 * sc, 0); 59 | pg.endShape(); 60 | pg.popStyle(); 61 | } 62 | 63 | //-----------behaviors--------------- 64 | 65 | void behavior(Graph graph) { 66 | // acceleration.add(steer(new Vector(mouseX,mouseY,300),true)); 67 | // acceleration.add(new Vector(0,.05,0)); 68 | if (avoidWalls) { 69 | acceleration.add(Vector.multiply(avoid(new Vector(node.position().x(), flockHeight, node.position().z())), 5)); 70 | acceleration.add(Vector.multiply(avoid(new Vector(node.position().x(), 0, node.position().z())), 5)); 71 | acceleration.add(Vector.multiply(avoid(new Vector(flockWidth, node.position().y(), node.position().z())), 5)); 72 | acceleration.add(Vector.multiply(avoid(new Vector(0, node.position().y(), node.position().z())), 5)); 73 | acceleration.add(Vector.multiply(avoid(new Vector(node.position().x(), node.position().y(), 0)), 5)); 74 | acceleration.add(Vector.multiply(avoid(new Vector(node.position().x(), node.position().y(), flockDepth)), 5)); 75 | } 76 | //alignment 77 | alignment = new Vector(); 78 | int alignmentCount = 0; 79 | //cohesion 80 | Vector posSum = new Vector(); 81 | int cohesionCount = 0; 82 | //separation 83 | separation = new Vector(); 84 | Vector repulse; 85 | for (int i = 0; i < flock.size(); i++) { 86 | Boid boid = flock.get(i); 87 | //alignment 88 | float distance = Vector.distance(node.position(), boid.node.position()); 89 | if (distance > 0 && distance <= neighborhoodRadius) { 90 | alignment.add(boid.velocity); 91 | alignmentCount++; 92 | } 93 | //cohesion 94 | float dist = dist(node.position().x(), node.position().y(), boid.node.position().x(), boid.node.position().y()); 95 | if (dist > 0 && dist <= neighborhoodRadius) { 96 | posSum.add(boid.node.position()); 97 | cohesionCount++; 98 | } 99 | //separation 100 | if (distance > 0 && distance <= neighborhoodRadius) { 101 | repulse = Vector.subtract(node.position(), boid.node.position()); 102 | repulse.normalize(); 103 | repulse.divide(distance); 104 | separation.add(repulse); 105 | } 106 | } 107 | //alignment 108 | if (alignmentCount > 0) { 109 | alignment.divide((float) alignmentCount); 110 | alignment.limit(maxSteerForce); 111 | } 112 | //cohesion 113 | if (cohesionCount > 0) 114 | posSum.divide((float) cohesionCount); 115 | cohesion = Vector.subtract(posSum, node.position()); 116 | cohesion.limit(maxSteerForce); 117 | acceleration.add(Vector.multiply(alignment, 1)); 118 | acceleration.add(Vector.multiply(cohesion, 3)); 119 | acceleration.add(Vector.multiply(separation, 1)); 120 | move(); 121 | checkBounds(); 122 | } 123 | 124 | Vector avoid(Vector target) { 125 | Vector steer = new Vector(); // creates vector for steering 126 | steer.set(Vector.subtract(node.position(), target)); // steering vector points away from 127 | steer.multiply(1 / sq(Vector.distance(node.position(), target))); 128 | return steer; 129 | } 130 | 131 | void move() { 132 | velocity.add(acceleration); // add acceleration to velocity 133 | velocity.limit(maxSpeed); // make sure the velocity vector magnitude does not 134 | // exceed maxSpeed 135 | node.translate(velocity); 136 | node.setOrientation(Quaternion.multiply(Quaternion.from(Vector.plusJ, atan2(-velocity.z(), velocity.x())), 137 | Quaternion.from(Vector.plusK, asin(velocity.y() / velocity.magnitude())))); 138 | acceleration.multiply(0); // reset acceleration 139 | } 140 | 141 | void checkBounds() { 142 | if (node.position().x() > flockWidth) 143 | node.position().setX(0); 144 | if (node.position().x() < 0) 145 | node.position().setX(flockWidth); 146 | if (node.position().y() > flockHeight) 147 | node.position().setY(0); 148 | if (node.position().y() < 0) 149 | node.position().setY(flockHeight); 150 | if (node.position().z() > flockDepth) 151 | node.position().setZ(0); 152 | if (node.position().z() < 0) 153 | node.position().setZ(flockDepth); 154 | } 155 | } -------------------------------------------------------------------------------- /examples/demos/FlockOfBoids/FlockOfBoids.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Flock of Boids 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example displays the famous artificial life program "Boids", developed by 6 | * Craig Reynolds in 1986 [1] and then adapted to Processing by Matt Wetmore in 7 | * 2010 (https://www.openprocessing.org/sketch/6910#), in 'third person' eye mode. 8 | * The Boid under the mouse will be colored blue. If you click on a boid it will 9 | * be selected as the scene avatar for the eye to follow it. 10 | * 11 | * 1. Reynolds, C. W. Flocks, Herds and Schools: A Distributed Behavioral Model. 87. 12 | * http://www.cs.toronto.edu/~dt/siggraph97-course/cwr87/ 13 | * 2. Check also this nice presentation about the paper: 14 | * https://pdfs.semanticscholar.org/73b1/5c60672971c44ef6304a39af19dc963cd0af.pdf 15 | * 3. Google for more... 16 | * 17 | * Press ' ' to switch between the different eye modes. 18 | * Press 'a' to toggle (start/stop) animation. 19 | * Press '+' to speed up the boids animation. 20 | * Press '-' to speed down the boids animation. 21 | * Press 'e' to enable concurrence of the flock animation. 22 | * Press 'd' to disable concurrence of the flock animation. 23 | * Press 'p' to print the current node rate. 24 | * Press 'm' to change the boid visual mode. 25 | * Press 'v' to toggle boids' wall skipping. 26 | * Press 's' to call scene.fit(1000). 27 | */ 28 | 29 | import nub.primitives.*; 30 | import nub.core.*; 31 | import nub.processing.*; 32 | 33 | Scene scene; 34 | //flock bounding box 35 | int flockWidth = 1280; 36 | int flockHeight = 720; 37 | int flockDepth = 600; 38 | boolean avoidWalls = true; 39 | boolean animate = true; 40 | 41 | int initBoidNum = 400; // amount of boids to start the program with 42 | ArrayList flock; 43 | Node avatar; 44 | 45 | void setup() { 46 | size(1000, 700, P3D); 47 | scene = new Scene(this, new Vector(flockWidth / 2, flockHeight / 2, flockDepth / 2), 800); 48 | // create and fill the list of boids 49 | flock = new ArrayList(); 50 | for (int i = 0; i < initBoidNum; i++) 51 | flock.add(new Boid(new Vector(flockWidth / 2, flockHeight / 2, flockDepth / 2))); 52 | } 53 | 54 | void draw() { 55 | background(10, 50, 25); 56 | ambientLight(128, 128, 128); 57 | directionalLight(255, 255, 255, 0, 1, -100); 58 | walls(); 59 | scene.render(); 60 | // uncomment to asynchronously update boid avatar. See mouseClicked() 61 | // updateAvatar(scene.node("mouseClicked")); 62 | } 63 | 64 | void walls() { 65 | pushStyle(); 66 | noFill(); 67 | stroke(255, 255, 0); 68 | line(0, 0, 0, 0, flockHeight, 0); 69 | line(0, 0, flockDepth, 0, flockHeight, flockDepth); 70 | line(0, 0, 0, flockWidth, 0, 0); 71 | line(0, 0, flockDepth, flockWidth, 0, flockDepth); 72 | line(flockWidth, 0, 0, flockWidth, flockHeight, 0); 73 | line(flockWidth, 0, flockDepth, flockWidth, flockHeight, flockDepth); 74 | line(0, flockHeight, 0, flockWidth, flockHeight, 0); 75 | line(0, flockHeight, flockDepth, flockWidth, flockHeight, flockDepth); 76 | line(0, 0, 0, 0, 0, flockDepth); 77 | line(0, flockHeight, 0, 0, flockHeight, flockDepth); 78 | line(flockWidth, 0, 0, flockWidth, 0, flockDepth); 79 | line(flockWidth, flockHeight, 0, flockWidth, flockHeight, flockDepth); 80 | popStyle(); 81 | } 82 | 83 | void updateAvatar(Node node) { 84 | if (node != avatar) { 85 | avatar = node; 86 | if (avatar != null) 87 | thirdPerson(); 88 | else if (scene.eye().reference() != null) 89 | resetEye(); 90 | } 91 | } 92 | 93 | // Sets current avatar as the eye reference and interpolate the eye to it 94 | void thirdPerson() { 95 | scene.eye().setReference(avatar); 96 | avatar.setWorldMagnitude(scene.eye()); 97 | scene.fit(avatar, 1000); 98 | } 99 | 100 | // Resets the eye 101 | void resetEye() { 102 | scene.eye().resetReference(); 103 | scene.lookAt(scene.center()); 104 | if (avatar != null) 105 | avatar.setMagnitude(1); 106 | scene.fit(1000); 107 | } 108 | 109 | // picks up a boid avatar, may be null 110 | void mouseClicked() { 111 | // two options to update the boid avatar: 112 | // 1. Synchronously 113 | updateAvatar(scene.updateTag("mouseClicked")); 114 | // which is the same as these two lines: 115 | // scene.updateTag("mouseClicked"); 116 | // updateAvatar(scene.node("mouseClicked")); 117 | // 2. Asynchronously 118 | // which requires updateAvatar(scene.node("mouseClicked")) to be called within draw() 119 | // scene.tag("mouseClicked"); 120 | } 121 | 122 | // 'first-person' interaction 123 | void mouseDragged() { 124 | if (scene.eye().reference() == null) 125 | if (mouseButton == LEFT) 126 | // same as: scene.spin(scene.eye()); 127 | scene.spin(); 128 | else if (mouseButton == RIGHT) 129 | // same as: scene.translate(scene.eye()); 130 | scene.shift(); 131 | else 132 | scene.moveForward(mouseX - pmouseX); 133 | } 134 | 135 | // highlighting and 'third-person' interaction 136 | void mouseMoved(MouseEvent event) { 137 | // 1. highlighting 138 | scene.tag("mouseMoved"); 139 | // 2. third-person interaction 140 | if (scene.eye().reference() != null) 141 | // press shift to move the mouse without looking around 142 | if (!event.isShiftDown()) 143 | scene.lookAround(); 144 | } 145 | 146 | void mouseWheel(MouseEvent event) { 147 | // same as: scene.zoom(event.getCount() * 20, scene.eye()); 148 | scene.zoom(event.getCount() * 20); 149 | } 150 | 151 | void keyPressed() { 152 | switch (key) { 153 | case 'a': 154 | animate = !animate; 155 | for (Boid boid : flock) { 156 | if (animate) { 157 | boid.startAnimation(); 158 | } 159 | else { 160 | boid.stopAnimation(); 161 | } 162 | } 163 | break; 164 | case 's': 165 | if (scene.eye().reference() == null) 166 | scene.fit(1000); 167 | break; 168 | case 'p': 169 | println("Frame rate: " + frameRate); 170 | break; 171 | case 'v': 172 | avoidWalls = !avoidWalls; 173 | break; 174 | case ' ': 175 | if (scene.eye().reference() != null) 176 | resetEye(); 177 | else if (avatar != null) 178 | thirdPerson(); 179 | break; 180 | } 181 | } -------------------------------------------------------------------------------- /examples/demos/MiniMap/MiniMap.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Mini Map 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example illustrates how to use off-screen rendering to build 6 | * a mini-map of the main scene where all objects are interactive. 7 | * Note that the minimap displays the projection of the scene onto 8 | * the near plane in 3D. 9 | * 10 | * Press ' ' to toggle the minimap display. 11 | * Press 'i' to toggle the interactivity of the minimap scene eye. 12 | * Press 'f' to show the entire scene or minimap. 13 | * Press 't' to toggle the scene camera type (only in 3D). 14 | */ 15 | 16 | import nub.primitives.*; 17 | import nub.core.*; 18 | import nub.processing.*; 19 | 20 | Scene scene, minimap, focus; 21 | Node[] models; 22 | boolean displayMinimap = true; 23 | // whilst scene is either on-screen or not, the minimap is always off-screen 24 | // test both cases here: 25 | boolean onScreen = false; 26 | boolean interactiveEye; 27 | 28 | //Choose P2D or P3D 29 | String renderer = P2D; 30 | 31 | void setup() { 32 | rectMode(CENTER); 33 | size(1920, 1080, renderer); 34 | scene = onScreen ? new Scene(this, 1000) : new Scene(createGraphics(width, height, renderer), 1000); 35 | scene.eye().enableHint(Node.BOUNDS | Node.BULLSEYE); 36 | scene.eye().disablePicking(Node.BULLSEYE); 37 | scene.eye().setBullsEyeSize(50); 38 | scene.eye().setHighlight(0); 39 | models = new Node[30]; 40 | for (int i = 0; i < models.length; i++) { 41 | if ((i & 1) == 0) { 42 | models[i] = new Node(shape()); 43 | } else { 44 | models[i] = new Node(); 45 | models[i].enableHint(Node.TORUS); 46 | models[i].scale(3); 47 | } 48 | scene.randomize(models[i]); 49 | } 50 | // Note that we pass the upper left corner coordinates where the minimap 51 | // is to be drawn (see drawing code below) to its constructor. 52 | minimap = new Scene(createGraphics(width / 2, height / 2, renderer), 2000); 53 | if (renderer == P3D) 54 | minimap.togglePerspective(); 55 | } 56 | 57 | PShape shape() { 58 | PShape shape = renderer == P3D ? createShape(BOX, 60) : createShape(RECT, 0, 0, 80, 100); 59 | shape.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 60 | return shape; 61 | } 62 | 63 | void keyPressed() { 64 | if (key == ' ') 65 | displayMinimap = !displayMinimap; 66 | if (key == 'i') { 67 | interactiveEye = !interactiveEye; 68 | if (interactiveEye) 69 | minimap.tag(scene.eye()); 70 | else 71 | minimap.untag(scene.eye()); 72 | } 73 | if (key == 'f') 74 | focus.fit(1000); 75 | if (key == 't') 76 | focus.togglePerspective(); 77 | if (key == 'p') 78 | scene.eye().togglePicking(Node.BULLSEYE | Node.BOUNDS); 79 | } 80 | 81 | void mouseMoved() { 82 | if (!interactiveEye || focus == scene) 83 | focus.tag(); 84 | } 85 | 86 | void mouseDragged() { 87 | if (mouseButton == LEFT) 88 | focus.spin(); 89 | else if (mouseButton == RIGHT) 90 | focus.shift(); 91 | else 92 | focus.zoom(focus.mouseDX()); 93 | } 94 | 95 | void mouseWheel(MouseEvent event) { 96 | if (renderer == P3D) 97 | focus.moveForward(event.getCount() * 40); 98 | else 99 | focus.zoom(event.getCount() * 40); 100 | } 101 | 102 | void mouseClicked(MouseEvent event) { 103 | if (event.getCount() == 2) 104 | if (event.getButton() == LEFT) 105 | focus.focus(); 106 | else 107 | focus.align(); 108 | } 109 | 110 | void draw() { 111 | focus = minimap.hasFocus() ? minimap : scene; 112 | scene.display(color(75, 25, 15)); 113 | if (displayMinimap) { 114 | minimap.display(color(125, 80, 90), width / 2, height / 2); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/depth.glsl: -------------------------------------------------------------------------------- 1 | // The fragment eye depth is obtained by solving z_e in terms z_n from here: 2 | // http://visualcomputing.github.io/Transformations/#/7/14 and: 3 | // http://visualcomputing.github.io/Transformations/#/7/15 4 | // yielding to: z_e = (2 * near * far) / (z_n * (far - near) - far - near) (eq1) 5 | 6 | uniform float near; 7 | uniform float far; 8 | 9 | // remapping of a value among 2 ranges: http://visualcomputing.github.io/Transformations/#/7/1 10 | // same as: https://processing.org/reference/map_.html 11 | float map(float value, float start1, float stop1, float start2, float stop2) { 12 | return start2 + (value - start1) * (stop2 - start2) / (stop1 - start1); 13 | } 14 | 15 | void main() { 16 | // z_n is obtained by remapping gl_FragCoord.z from [0..1] to [-1..1] 17 | float z_n = map(gl_FragCoord.z, 0, 1, -1, 1); 18 | // eq 1 19 | float z_e = (2 * near * far) / (z_n * (far - near) - far - near); 20 | // the normalized eye depth is obtained by remapping z_e from [-near..-far] to [0..1] 21 | float depth = map(z_e, -near, -far, 0, 1); 22 | // render the depth as a grey scale color 23 | gl_FragColor = vec4(vec3(depth), 1); 24 | } -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/edge.glsl: -------------------------------------------------------------------------------- 1 | varying vec4 vertTexCoord; 2 | 3 | uniform sampler2D tex; 4 | uniform vec2 aspect; 5 | 6 | vec2 texel = vec2(aspect.x, aspect.y); 7 | 8 | mat3 G[9]; 9 | 10 | mat3 G0 = mat3( 0.5/sqrt(2.0), 0, -0.5/sqrt(2.0), 0.5, 0, -0.5, 0.5/sqrt(2.0), 0, -0.5/sqrt(2.0) ); 11 | mat3 G1 = mat3( 0.5/sqrt(2.0), 0.5, 0.5/sqrt(2.0), 0, 0, 0, -0.5/sqrt(2.0), -0.5, -0.5/sqrt(2.0) ); 12 | mat3 G2 = mat3( 0, -0.5/sqrt(2.0), 0.5, 0.5/sqrt(2.0), 0, -0.5/sqrt(2.0), -0.5, 0.5/sqrt(2.0), 0 ); 13 | mat3 G3 = mat3( 0.5, -0.5/sqrt(2.0), 0, -0.5/sqrt(2.0), 0, 0.5/sqrt(2.0), 0, 0.5/sqrt(2.0), -0.5 ); 14 | mat3 G4 = mat3( 0, 0.5, 0, -0.5, 0, -0.5, 0, 0.5, 0); 15 | mat3 G5 = mat3( -0.5, 0, 0.5, 0, 0, 0, 0.5, 0, -0.5 ); 16 | mat3 G6 = mat3( 1.0/6.0, -1.0/3.0, 1.0/6.0, -1.0/3.0, 2.0/3.0, -1.0/3.0, 1.0/6.0, -1.0/3.0, 1.0/6.0 ); 17 | mat3 G7 = mat3( -1.0/3.0, 1.0/6.0, -1.0/3.0, 1.0/6.0, 2.0/3.0, 1.0/6.0, -1.0/3.0, 1.0/6.0, -1.0/3.0); 18 | mat3 G8 = mat3( 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0, 1.0/3.0 ); 19 | 20 | void main(void) 21 | { 22 | G[0] = G0; 23 | G[1] = G1; 24 | G[2] = G2; 25 | G[3] = G3; 26 | G[4] = G4; 27 | G[5] = G5; 28 | G[6] = G6; 29 | G[7] = G7; 30 | G[8] = G8; 31 | 32 | mat3 I; 33 | float cnv[9]; 34 | vec3 s; 35 | 36 | for (float i=0.0; i<3.0; i++) 37 | { 38 | for (float j=0.0; j<3.0; j++) 39 | { 40 | s = texture2D(tex, vertTexCoord.st + texel * vec2(i-1.0,j-1.0)).rgb; 41 | I[int(i)][int(j)] = length(s); 42 | } 43 | } 44 | 45 | for (int i=0; i<9; i++) 46 | { 47 | float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]); 48 | cnv[i] = dp3 * dp3; 49 | } 50 | 51 | float M = (cnv[0] + cnv[1]) + (cnv[2] + cnv[3]); 52 | float S = (cnv[4] + cnv[5]) + (cnv[6] + cnv[7]) + (cnv[8] + M); 53 | 54 | gl_FragColor = vec4(vec3(sqrt(M/S)), 1.0); 55 | } 56 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/horizontal.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D tDiffuse; 2 | uniform float h; 3 | uniform float r; 4 | 5 | varying vec4 vertTexCoord; 6 | 7 | void main() { 8 | vec2 vUv = vertTexCoord.st; 9 | vec4 sum = vec4( 0.0 ); 10 | 11 | float hh = h * abs( r - vUv.y ); 12 | 13 | sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051; 14 | sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918; 15 | sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245; 16 | sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531; 17 | sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633; 18 | sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531; 19 | sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245; 20 | sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918; 21 | sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051; 22 | 23 | gl_FragColor = sum; 24 | } 25 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/kaleido.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D tex; 2 | uniform float segments; 3 | 4 | varying vec4 vertTexCoord; 5 | 6 | void main() 7 | { 8 | vec2 uv = vertTexCoord.st; 9 | vec2 normed = 2.0 * uv - 1.0; 10 | float r = length(normed); 11 | float theta = atan(normed.y / abs(normed.x)); 12 | theta *= segments; 13 | 14 | vec2 newUv = (vec2(r * cos(theta), r * sin(theta)) + 1.0) / 2.0; 15 | 16 | gl_FragColor = texture2D(tex, newUv); 17 | } 18 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/noise.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D tex; 2 | 3 | varying vec4 vertexture; 4 | varying vec4 vertTexCoord; 5 | 6 | uniform float frequency; 7 | uniform float amplitude; 8 | uniform float time; 9 | uniform float speed; 10 | 11 | vec3 mod289(vec3 x) { 12 | return x - floor(x * (1.0 / 289.0)) * 289.0; 13 | } 14 | 15 | vec4 mod289(vec4 x) { 16 | return x - floor(x * (1.0 / 289.0)) * 289.0; 17 | } 18 | 19 | vec4 permute(vec4 x) { 20 | return mod289(((x*34.0)+1.0)*x); 21 | } 22 | 23 | vec4 taylorInvSqrt(vec4 r){ 24 | return 1.79284291400159 - 0.85373472095314 * r; 25 | } 26 | 27 | float snoise(vec3 v){ 28 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 29 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 30 | 31 | // First corner 32 | vec3 i = floor(v + dot(v, C.yyy) ); 33 | vec3 x0 = v - i + dot(i, C.xxx) ; 34 | 35 | // Other corners 36 | vec3 g = step(x0.yzx, x0.xyz); 37 | vec3 l = 1.0 - g; 38 | vec3 i1 = min( g.xyz, l.zxy ); 39 | vec3 i2 = max( g.xyz, l.zxy ); 40 | 41 | // x0 = x0 - 0.0 + 0.0 * C.xxx; 42 | // x1 = x0 - i1 + 1.0 * C.xxx; 43 | // x2 = x0 - i2 + 2.0 * C.xxx; 44 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 45 | vec3 x1 = x0 - i1 + C.xxx; 46 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 47 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 48 | 49 | // Permutations 50 | i = mod289(i); 51 | vec4 p = permute( permute( permute( 52 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 53 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 54 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 55 | 56 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 57 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 58 | float n_ = 0.142857142857; // 1.0/7.0 59 | vec3 ns = n_ * D.wyz - D.xzx; 60 | 61 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 62 | 63 | vec4 x_ = floor(j * ns.z); 64 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 65 | 66 | vec4 x = x_ *ns.x + ns.yyyy; 67 | vec4 y = y_ *ns.x + ns.yyyy; 68 | vec4 h = 1.0 - abs(x) - abs(y); 69 | 70 | vec4 b0 = vec4( x.xy, y.xy ); 71 | vec4 b1 = vec4( x.zw, y.zw ); 72 | 73 | //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 74 | //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 75 | vec4 s0 = floor(b0)*2.0 + 1.0; 76 | vec4 s1 = floor(b1)*2.0 + 1.0; 77 | vec4 sh = -step(h, vec4(0.0)); 78 | 79 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 80 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 81 | 82 | vec3 p0 = vec3(a0.xy,h.x); 83 | vec3 p1 = vec3(a0.zw,h.y); 84 | vec3 p2 = vec3(a1.xy,h.z); 85 | vec3 p3 = vec3(a1.zw,h.w); 86 | 87 | //Normalise gradients 88 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 89 | p0 *= norm.x; 90 | p1 *= norm.y; 91 | p2 *= norm.z; 92 | p3 *= norm.w; 93 | 94 | // Mix final noise value 95 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 96 | m = m * m; 97 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 98 | dot(p2,x2), dot(p3,x3) ) ); 99 | } 100 | // end of noise functions 101 | 102 | void main() 103 | { 104 | vec2 texCoords = vertTexCoord.st + vec2( 105 | amplitude * (snoise(vec3(frequency * vertTexCoord.s, frequency * vertTexCoord.t, speed * time))), 106 | amplitude * (snoise(vec3(frequency * vertTexCoord.s + 17.0, frequency * vertTexCoord.t, speed * time))) 107 | ); 108 | gl_FragColor = texture2D(tex, texCoords); 109 | } 110 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/pixelate.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D tex; 2 | uniform float xPixels; 3 | uniform float yPixels; 4 | 5 | varying vec4 vertTexCoord; 6 | 7 | uniform sampler2D tDepth; 8 | 9 | void main() 10 | { 11 | vec2 texCoords = vec2(floor(vertTexCoord.s * xPixels) / xPixels, floor(vertTexCoord.t * yPixels) / yPixels); 12 | gl_FragColor = texture2D(tex, texCoords); 13 | } 14 | -------------------------------------------------------------------------------- /examples/demos/PostEffects/data/raysfrag.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D rtex; 2 | uniform sampler2D otex; 3 | 4 | const int NUM_SAMPLES = 50; 5 | 6 | uniform vec2 lightPositionOnScreen; 7 | uniform float lightDirDOTviewDir; 8 | 9 | varying vec4 vertTexCoord; 10 | 11 | void main(void) 12 | { 13 | vec4 origColor = texture2D(otex, vertTexCoord.st); 14 | vec4 raysColor = texture2D(rtex, vertTexCoord.st); 15 | 16 | if (lightDirDOTviewDir>0.0){ 17 | float exposure = 0.1/float(NUM_SAMPLES); 18 | float decay = 1.0 ; 19 | float density = 0.5; 20 | float weight = 6.0; 21 | float illuminationDecay = 1.0; 22 | 23 | vec2 deltaTextCoord = vec2( vertTexCoord.st - lightPositionOnScreen); 24 | vec2 textCoo = vertTexCoord.st; 25 | deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density; 26 | 27 | for(int i=0; i < NUM_SAMPLES ; i++) 28 | { 29 | textCoo -= deltaTextCoord; 30 | vec4 tsample = texture2D(rtex, textCoo ); 31 | tsample *= illuminationDecay * weight; 32 | raysColor += tsample; 33 | illuminationDecay *= decay; 34 | } 35 | raysColor *= exposure * lightDirDOTviewDir; 36 | float p = 0.3 *raysColor.g + 0.59*raysColor.r + 0.11*raysColor.b; 37 | gl_FragColor = origColor + p; 38 | } else { 39 | gl_FragColor = origColor; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/demos/ShadowMapping/data/depth_frag.glsl: -------------------------------------------------------------------------------- 1 | vec4 packDepth(float depth) { 2 | float depthFrac = fract(depth * 255.0); 3 | return vec4(depth - depthFrac / 255.0, depthFrac, 1.0, 1.0); 4 | } 5 | 6 | void main(void) { 7 | gl_FragColor = packDepth(gl_FragCoord.z); 8 | } -------------------------------------------------------------------------------- /examples/demos/ShadowMapping/data/shadow_frag.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Used a bigger poisson disk kernel than in the tutorial to get smoother results 4 | const vec2 poissonDisk[9] = vec2[] ( 5 | vec2(0.95581, -0.18159), vec2(0.50147, -0.35807), vec2(0.69607, 0.35559), 6 | vec2(-0.0036825, -0.59150), vec2(0.15930, 0.089750), vec2(-0.65031, 0.058189), 7 | vec2(0.11915, 0.78449), vec2(-0.34296, 0.51575), vec2(-0.60380, -0.41527) 8 | ); 9 | 10 | // Unpack the 16bit depth float from the first two 8bit channels of the rgba vector 11 | float unpackDepth(vec4 color) { 12 | return color.r + color.g / 255.0; 13 | } 14 | 15 | uniform sampler2D shadowMap; 16 | varying vec4 vertColor; 17 | varying vec4 shadowCoord; 18 | varying float lightIntensity; 19 | 20 | void main(void) { 21 | // Project shadow coords, needed for a perspective light matrix (spotlight) 22 | vec3 shadowCoordProj = shadowCoord.xyz / shadowCoord.w; 23 | 24 | // Only render shadow if fragment is facing the light 25 | if (lightIntensity > 0.5) { 26 | float visibility = 9.0; 27 | // I used step() instead of branching, should be much faster this way 28 | for (int n = 0; n < 9; ++n) 29 | visibility += step(shadowCoordProj.z, unpackDepth(texture2D(shadowMap, shadowCoordProj.xy + poissonDisk[n] / 512.0))); 30 | gl_FragColor = vec4(vertColor.rgb * min(visibility * 0.05556, lightIntensity), vertColor.a); 31 | } else 32 | gl_FragColor = vec4(vertColor.rgb * lightIntensity, vertColor.a); 33 | } 34 | -------------------------------------------------------------------------------- /examples/demos/ShadowMapping/data/shadow_vert.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 transform; 2 | uniform mat4 modelview; 3 | uniform mat3 normalMatrix; 4 | uniform mat4 shadowTransform; 5 | uniform vec3 lightDirection; 6 | 7 | attribute vec4 vertex; 8 | attribute vec4 color; 9 | attribute vec3 normal; 10 | 11 | varying vec4 vertColor; 12 | varying vec4 shadowCoord; 13 | varying float lightIntensity; 14 | 15 | void main() { 16 | vertColor = color; 17 | vec3 vertNormal = normalize(normalMatrix * normal);// Get normal direction in model view space 18 | vec4 vertPosition = modelview * vertex; 19 | shadowCoord = shadowTransform * (vertPosition + vec4(vertNormal, 0.0));// Normal bias removes the shadow acne 20 | lightIntensity = 0.5 + dot(-lightDirection, vertNormal) * 0.5; 21 | gl_Position = transform * vertex; 22 | } 23 | -------------------------------------------------------------------------------- /examples/demos/ViewFrustumCulling/ViewFrustumCulling.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * View Frustum Culling. 3 | * by Jean Pierre Charalambos. 4 | * 5 | * This example illustrates a basic view frustum culling implementation which 6 | * is performed by analytically solving the frustum plane equations. 7 | * 8 | * A customized traversal rendering algorithm is implemented by adding a custom 9 | * node behavior for the main scene to clip an octree against the camera's viewing 10 | * frustum. A second viewer displays an external view of the main frustum scene 11 | * (using the main scene eye BOUNDS hint) and the clipped octree. 12 | * 13 | * Press the space-bar to change the scene type: PERSPECTIVE or ORTHOGRAPHIC. 14 | */ 15 | 16 | import nub.primitives.*; 17 | import nub.core.*; 18 | import nub.processing.*; 19 | 20 | Node root; 21 | Scene mainScene, secondaryScene, focus; 22 | 23 | int w = 1400; 24 | int h = 1400; 25 | //octree 26 | float a = 220, b = 100, c = 280; 27 | int levels = 4; 28 | 29 | void settings() { 30 | size(w, h, P3D); 31 | } 32 | 33 | void setup() { 34 | // main scene 35 | mainScene = new Scene(createGraphics(w, h / 2, P3D)); 36 | mainScene.eye().enableHint(Node.BOUNDS); 37 | mainScene.togglePerspective(); 38 | mainScene.fit(1000); 39 | // secondary scene 40 | secondaryScene = new Scene(createGraphics(w, h / 2, P3D), 200); 41 | secondaryScene.togglePerspective(); 42 | // declare and build the octree hierarchy 43 | root = node(null, new Vector()); 44 | buildOctree(root); 45 | } 46 | 47 | void buildOctree(Node parent) { 48 | if (level(parent) < levels) 49 | for (int i = 0; i < 8; ++i) 50 | buildOctree(node(parent, new Vector((i & 4) == 0 ? a : -a, (i & 2) == 0 ? b : -b, (i & 1) == 0 ? c : -c))); 51 | } 52 | 53 | float level(Node node) { 54 | return 1 - log(node.worldMagnitude()) / log(2); 55 | } 56 | 57 | Node node(Node parent, Vector vector) { 58 | Node node = new Node(parent); 59 | node.scale(parent == null ? 1 : 0.5); 60 | node.translate(Vector.multiply(vector, node.magnitude() / 2)); 61 | node.tagging = false; 62 | node.setShape((PGraphics pg) -> { 63 | float level = level(node); 64 | pg.stroke(color(0.3 * level * 255, 0.2 * 255, (1 - 0.3 * level) * 255)); 65 | pg.strokeWeight(pow(2, levels - 1)); 66 | pg.noFill(); 67 | pg.box(a, b, c); 68 | }); 69 | // register the culling method only at the main scene 70 | mainScene.addBehavior(node, this::cull); 71 | return node; 72 | } 73 | 74 | 75 | // The culling method is called before the node is rendered 76 | void cull(Node node) { 77 | switch (mainScene.boxVisibility(node.worldLocation(new Vector(-a / 2, -b / 2, -c / 2)), 78 | node.worldLocation(new Vector(a / 2, b / 2, c / 2)))) { 79 | case VISIBLE: 80 | for (Node child : node.children()) 81 | child.cull = true; 82 | break; 83 | case SEMIVISIBLE: 84 | if (!node.children().isEmpty()) { 85 | // don't render the node... 86 | node.bypass(); 87 | // ... but don't cull its children either 88 | for (Node child : node.children()) 89 | child.cull = false; 90 | } 91 | break; 92 | case INVISIBLE: 93 | node.cull = true; 94 | break; 95 | } 96 | } 97 | 98 | void draw() { 99 | focus = mainScene.hasFocus() ? mainScene : secondaryScene; 100 | // culling condition should be retested every frame 101 | root.cull = false; 102 | mainScene.display(color(75, 205, 65)); 103 | secondaryScene.display(color(185), 0, h / 2); 104 | } 105 | 106 | void mouseDragged() { 107 | if (mouseButton == LEFT) 108 | focus.spin(); 109 | else if (mouseButton == RIGHT) 110 | focus.shift(); 111 | else 112 | focus.zoom(mouseX - pmouseX); 113 | } 114 | 115 | void mouseWheel(MouseEvent event) { 116 | focus.moveForward(event.getCount() * 20); 117 | } 118 | 119 | void mouseClicked(MouseEvent event) { 120 | if (event.getCount() == 2) 121 | if (event.getButton() == LEFT) 122 | focus.focus(); 123 | else 124 | focus.align(); 125 | } 126 | 127 | void keyPressed() { 128 | if (key == ' ') 129 | focus.togglePerspective(); 130 | if (key == 'f') { 131 | Scene.leftHanded = !Scene.leftHanded; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | The lib folder: 2 | In case your library requires 3rd party libraries, which need to be 3 | added to the distribution, put them into the lib folder. 4 | These 3rd party libraries will be added to your distribution and are 5 | located next to your library's jar file. 6 | This does not apply to .jar files that are considered core processing libraries. -------------------------------------------------------------------------------- /natives/core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/core.jar -------------------------------------------------------------------------------- /natives/gluegen-rt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/gluegen-rt.jar -------------------------------------------------------------------------------- /natives/jogl-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/jogl-all.jar -------------------------------------------------------------------------------- /natives/linux-aarch64/libgluegen_rt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libgluegen_rt.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libjogl_desktop.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libjogl_desktop.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libjogl_mobile.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libjogl_mobile.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libnativewindow_awt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libnativewindow_awt.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libnativewindow_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libnativewindow_drm.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libnativewindow_x11.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libnativewindow_x11.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libnewt_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libnewt_drm.so -------------------------------------------------------------------------------- /natives/linux-aarch64/libnewt_head.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-aarch64/libnewt_head.so -------------------------------------------------------------------------------- /natives/linux-amd64/libgluegen_rt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libgluegen_rt.so -------------------------------------------------------------------------------- /natives/linux-amd64/libjogl_desktop.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libjogl_desktop.so -------------------------------------------------------------------------------- /natives/linux-amd64/libjogl_mobile.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libjogl_mobile.so -------------------------------------------------------------------------------- /natives/linux-amd64/libnativewindow_awt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libnativewindow_awt.so -------------------------------------------------------------------------------- /natives/linux-amd64/libnativewindow_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libnativewindow_drm.so -------------------------------------------------------------------------------- /natives/linux-amd64/libnativewindow_x11.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libnativewindow_x11.so -------------------------------------------------------------------------------- /natives/linux-amd64/libnewt_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libnewt_drm.so -------------------------------------------------------------------------------- /natives/linux-amd64/libnewt_head.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-amd64/libnewt_head.so -------------------------------------------------------------------------------- /natives/linux-arm/libgluegen_rt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libgluegen_rt.so -------------------------------------------------------------------------------- /natives/linux-arm/libjogl_desktop.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libjogl_desktop.so -------------------------------------------------------------------------------- /natives/linux-arm/libjogl_mobile.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libjogl_mobile.so -------------------------------------------------------------------------------- /natives/linux-arm/libnativewindow_awt.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libnativewindow_awt.so -------------------------------------------------------------------------------- /natives/linux-arm/libnativewindow_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libnativewindow_drm.so -------------------------------------------------------------------------------- /natives/linux-arm/libnativewindow_x11.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libnativewindow_x11.so -------------------------------------------------------------------------------- /natives/linux-arm/libnewt_drm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libnewt_drm.so -------------------------------------------------------------------------------- /natives/linux-arm/libnewt_head.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/linux-arm/libnewt_head.so -------------------------------------------------------------------------------- /natives/macos-aarch64/libgluegen_rt.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libgluegen_rt.dylib -------------------------------------------------------------------------------- /natives/macos-aarch64/libjogl_desktop.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libjogl_desktop.dylib -------------------------------------------------------------------------------- /natives/macos-aarch64/libjogl_mobile.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libjogl_mobile.dylib -------------------------------------------------------------------------------- /natives/macos-aarch64/libnativewindow_awt.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libnativewindow_awt.dylib -------------------------------------------------------------------------------- /natives/macos-aarch64/libnativewindow_macosx.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libnativewindow_macosx.dylib -------------------------------------------------------------------------------- /natives/macos-aarch64/libnewt_head.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-aarch64/libnewt_head.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libgluegen_rt.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libgluegen_rt.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libjogl_desktop.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libjogl_desktop.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libjogl_mobile.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libjogl_mobile.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libnativewindow_awt.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libnativewindow_awt.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libnativewindow_macosx.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libnativewindow_macosx.dylib -------------------------------------------------------------------------------- /natives/macos-x86_64/libnewt_head.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/macos-x86_64/libnewt_head.dylib -------------------------------------------------------------------------------- /natives/windows-amd64/fenster.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/fenster.exe -------------------------------------------------------------------------------- /natives/windows-amd64/gluegen_rt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/gluegen_rt.dll -------------------------------------------------------------------------------- /natives/windows-amd64/jogl_desktop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/jogl_desktop.dll -------------------------------------------------------------------------------- /natives/windows-amd64/jogl_mobile.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/jogl_mobile.dll -------------------------------------------------------------------------------- /natives/windows-amd64/nativewindow_awt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/nativewindow_awt.dll -------------------------------------------------------------------------------- /natives/windows-amd64/nativewindow_win32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/nativewindow_win32.dll -------------------------------------------------------------------------------- /natives/windows-amd64/newt_head.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/natives/windows-amd64/newt_head.dll -------------------------------------------------------------------------------- /resources/README.md: -------------------------------------------------------------------------------- 1 | ## How to install ##library.name## 2 | 3 | ### Install with the Contribution Manager 4 | 5 | Add contributed Libraries by selecting the menu item _Sketch_ → _Import Library..._ → _Add Library..._ This will open the Contribution Manager, where you can browse for ##library.name##, or any other Library you want to install. 6 | 7 | Not all available Libraries have been converted to show up in this menu. If a Library isn't there, it will need to be installed manually by following the instructions below. 8 | 9 | ### Manual Install 10 | 11 | Contributed Libraries may be downloaded separately and manually placed within the `libraries` folder of your Processing sketchbook. To find (and change) the Processing sketchbook location on your computer, open the Preferences window from the Processing application (PDE) and look for the "Sketchbook location" item at the top. 12 | 13 | By default the following locations are used for your sketchbook folder: 14 | * For Mac users, the sketchbook folder is located inside `~/Documents/Processing` 15 | * For Windows users, the sketchbook folder is located inside `My Documents/Processing` 16 | 17 | Download ##library.name## from ##library.url## 18 | 19 | Unzip and copy the contributed Library's folder into the `libraries` folder in the Processing sketchbook. You will need to create this `libraries` folder if it does not exist. 20 | 21 | The folder structure for Library ##library.name## should be as follows: 22 | 23 | ``` 24 | Processing 25 | libraries 26 | ##library.name## 27 | examples 28 | library 29 | ##library.name##.jar 30 | reference 31 | src 32 | ``` 33 | 34 | Some folders like `examples` or `src` might be missing. After Library ##library.name## has been successfully installed, restart the Processing application. 35 | 36 | ### Troubleshooting 37 | 38 | If you're having trouble, have a look at the [Processing Wiki](https://github.com/processing/processing/wiki/How-to-Install-a-Contributed-Library) for more information, or contact the author [##author.name##](##author.url##). 39 | -------------------------------------------------------------------------------- /resources/code/ExampleTaglet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/resources/code/ExampleTaglet.class -------------------------------------------------------------------------------- /resources/code/ant-contrib-1.0b3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/resources/code/ant-contrib-1.0b3.jar -------------------------------------------------------------------------------- /resources/code/doc.sh: -------------------------------------------------------------------------------- 1 | # a shell script to create a java documentation 2 | # for a processing library. 3 | # 4 | # make changes to the variables below so they 5 | # fit the structure of your library 6 | 7 | # the package name of your library 8 | package=template; 9 | 10 | # source folder location 11 | src=../src; 12 | 13 | # the destination folder of your documentation 14 | dest=../documentation; 15 | 16 | 17 | # compile the java documentation 18 | javadoc -d $dest -stylesheetfile ./stylesheet.css -sourcepath ${src} ${package} 19 | -------------------------------------------------------------------------------- /resources/library.properties: -------------------------------------------------------------------------------- 1 | name = ##library.name## 2 | authors = [##author.name##](##author.url##) 3 | url = ##library.url## 4 | categories = ##library.categories## 5 | sentence = ##library.sentence## 6 | paragraph = ##library.paragraph## 7 | version = ##library.version## 8 | prettyVersion = ##library.prettyVersion## 9 | minRevision = ##compatible.minRevision## 10 | maxRevision = ##compatible.maxRevision## -------------------------------------------------------------------------------- /resources/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | /* Define colors, fonts and other style attributes here to override the defaults */ 3 | /* processingLibs style by andreas schlegel, sojamo */ 4 | 5 | 6 | body { 7 | margin : 0; 8 | padding : 0; 9 | padding-left : 10px; 10 | padding-right : 8px; 11 | background-color : #FFFFFF; 12 | font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; 13 | font-size : 100%; 14 | font-size : 0.7em; 15 | font-weight : normal; 16 | line-height : normal; 17 | margin-bottom:30px; 18 | } 19 | 20 | 21 | 22 | 23 | /* Headings */ 24 | h1, h2, h3, h4, h5, th { 25 | font-family :Arial, Helvetica, sans-serif; 26 | font-size:1.2em; 27 | } 28 | 29 | 30 | p { 31 | font-size : 1em; 32 | width:80%; 33 | } 34 | 35 | pre, code { 36 | font-family : "Courier New", Courier, monospace; 37 | font-size : 12px; 38 | line-height : normal; 39 | } 40 | 41 | 42 | 43 | table { 44 | border:0; 45 | margin-bottom:10px; 46 | margin-top:10px; 47 | } 48 | 49 | 50 | tr, td { 51 | border-top: 0px solid; 52 | border-left: 0px solid; 53 | padding-top:8px; 54 | padding-bottom:8px; 55 | } 56 | 57 | 58 | 59 | hr { 60 | border:0; 61 | height:1px; 62 | padding:0; 63 | margin:0; 64 | margin-bottom:4px; 65 | 66 | } 67 | 68 | 69 | 70 | dd, th, td, font { 71 | font-size:1.0em; 72 | line-height:1.0em; 73 | } 74 | 75 | 76 | 77 | dt { 78 | margin-bottom:0px; 79 | } 80 | 81 | 82 | 83 | dd { 84 | margin-top:2px; 85 | margin-bottom:4px; 86 | } 87 | 88 | 89 | 90 | a { 91 | text-decoration: underline; 92 | font-weight: normal; 93 | } 94 | 95 | a:hover, 96 | a:active { 97 | text-decoration: underline; 98 | font-weight: normal; 99 | } 100 | 101 | a:visited, 102 | a:link:visited { 103 | text-decoration: underline; 104 | font-weight: normal; 105 | } 106 | 107 | 108 | img { 109 | border: 0px solid #000000; 110 | } 111 | 112 | 113 | 114 | /* Navigation bar fonts */ 115 | .NavBarCell1 { 116 | border:0; 117 | } 118 | 119 | .NavBarCell1Rev { 120 | border:0; 121 | } 122 | 123 | .NavBarFont1 { 124 | font-family: Arial, Helvetica, sans-serif; 125 | font-size:1.1em; 126 | } 127 | 128 | 129 | .NavBarFont1 b { 130 | font-weight:normal; 131 | } 132 | 133 | 134 | 135 | .NavBarFont1:after, .NavBarFont1Rev:after { 136 | font-weight:normal; 137 | content: " \\"; 138 | } 139 | 140 | 141 | .NavBarFont1Rev { 142 | font-family: Arial, Helvetica, sans-serif; 143 | font-size:1.1em; 144 | } 145 | 146 | .NavBarFont1Rev b { 147 | font-family: Arial, Helvetica, sans-serif; 148 | font-size:1.1em; 149 | font-weight:normal; 150 | } 151 | 152 | .NavBarCell2 { 153 | font-family: Arial, Helvetica, sans-serif; 154 | } 155 | 156 | .NavBarCell3 { 157 | font-family: Arial, Helvetica, sans-serif; 158 | } 159 | 160 | 161 | 162 | font.FrameItemFont { 163 | font-family: Helvetica, Arial, sans-serif; 164 | font-size:1.1em; 165 | line-height:1.1em; 166 | } 167 | 168 | font.FrameHeadingFont { 169 | font-family: Helvetica, Arial, sans-serif; 170 | line-height:32px; 171 | } 172 | 173 | /* Font used in left-hand node lists */ 174 | .FrameTitleFont { 175 | font-family: Helvetica, Arial, sans-serif 176 | } 177 | 178 | 179 | .toggleList { 180 | padding:0; 181 | margin:0; 182 | margin-top:12px; 183 | } 184 | 185 | .toggleList dt { 186 | font-weight:bold; 187 | font-size:12px; 188 | font-family:arial,sans-serif; 189 | padding:0px; 190 | margin:10px 0px 10px 0px; 191 | } 192 | 193 | .toggleList dt span { 194 | font-family: monospace; 195 | padding:0; 196 | margin:0; 197 | } 198 | 199 | 200 | .toggleList dd { 201 | margin:0; 202 | padding:0; 203 | } 204 | 205 | html.isjs .toggleList dd { 206 | display: none; 207 | } 208 | 209 | .toggleList pre { 210 | padding: 4px 4px 4px 4px; 211 | } 212 | 213 | 214 | 215 | 216 | 217 | /* COLORS */ 218 | 219 | pre, code { 220 | color: #000000; 221 | } 222 | 223 | 224 | body { 225 | color : #333333; 226 | background-color :#FFFFFF; 227 | } 228 | 229 | 230 | h1, h2, h3, h4, h5, h6 { 231 | color:#555; 232 | } 233 | 234 | a, 235 | .toggleList dt { 236 | color: #1a7eb0; 237 | } 238 | 239 | a:hover, 240 | a:active { 241 | color: #1a7eb0; 242 | } 243 | 244 | a:visited, 245 | a:link:visited { 246 | color: #1a7eb0; 247 | } 248 | 249 | td,tr { 250 | border-color: #999999; 251 | } 252 | 253 | hr { 254 | color:#999999; 255 | background:#999999; 256 | } 257 | 258 | 259 | .TableHeadingColor { 260 | background: #dcdcdc; 261 | color: #555; 262 | } 263 | 264 | 265 | .TableSubHeadingColor { 266 | background: #EEEEFF 267 | } 268 | 269 | .TableRowColor { 270 | background: #FFFFFF 271 | } 272 | 273 | 274 | .NavBarCell1 { 275 | background-color:#dcdcdc; 276 | color:#000; 277 | } 278 | 279 | .NavBarCell1 a { 280 | color:#333; 281 | } 282 | 283 | 284 | .NavBarCell1Rev { 285 | background-color:transparent; 286 | } 287 | 288 | .NavBarFont1 { 289 | color:#333; 290 | } 291 | 292 | 293 | .NavBarFont1Rev { 294 | color:#fff; 295 | } 296 | 297 | .NavBarCell2 { 298 | background-color:#999; 299 | } 300 | 301 | .NavBarCell2 a { 302 | color:#fff; 303 | } 304 | 305 | 306 | 307 | .NavBarCell3 { 308 | background-color:#dcdcdc; 309 | } 310 | 311 | -------------------------------------------------------------------------------- /src/nub/core/Inertia.java: -------------------------------------------------------------------------------- 1 | /*************************************************************************************** 2 | * nub 3 | * Copyright (c) 2019-2021 Universidad Nacional de Colombia 4 | * @author Jean Pierre Charalambos, https://github.com/VisualComputing 5 | * 6 | * All rights reserved. A simple, expressive, language-agnostic, and extensible visual 7 | * computing library, featuring interaction, visualization and animation frameworks and 8 | * supporting advanced (onscreen/offscreen) (real/non-real time) rendering techniques. 9 | * Released under the terms of the GPLv3, refer to: http://www.gnu.org/licenses/gpl.html 10 | ***************************************************************************************/ 11 | 12 | package nub.core; 13 | 14 | import nub.primitives.Vector; 15 | 16 | /** 17 | * Translate, Orbit & Rotate (Euler angles) damped task based on PeasyCam, see 18 | * DampedAction 1) 34 | val /= 10; 35 | if (val != inertia) 36 | System.out.println("Warning: inertia should be in [0..1]. Setting it as " + val); 37 | _inertia = val; 38 | } 39 | 40 | void _execute() { 41 | if (_active) { 42 | _x *= _inertia; 43 | if (Math.abs(_x) < .001) 44 | _x = 0; 45 | _y *= _inertia; 46 | if (Math.abs(_y) < .001) 47 | _y = 0; 48 | _z *= _inertia; 49 | if (Math.abs(_z) < .001) 50 | _z = 0; 51 | if (_x == 0 && _y == 0 && _z == 0) 52 | _active = false; 53 | else 54 | _action(); 55 | } 56 | } 57 | 58 | /** 59 | * Callback method for translate, orbit & rotate damped actions. 60 | */ 61 | abstract void _action(); 62 | } 63 | -------------------------------------------------------------------------------- /src/nub/processing/GLMatrixHandler.java: -------------------------------------------------------------------------------- 1 | /*************************************************************************************** 2 | * nub 3 | * Copyright (c) 2019-2021 Universidad Nacional de Colombia 4 | * @author Jean Pierre Charalambos, https://github.com/VisualComputing 5 | * 6 | * All rights reserved. A simple, expressive, language-agnostic, and extensible visual 7 | * computing library, featuring interaction, visualization and animation frameworks and 8 | * supporting advanced (onscreen/offscreen) (real/non-real time) rendering techniques. 9 | * Released under the terms of the GPLv3, refer to: http://www.gnu.org/licenses/gpl.html 10 | ***************************************************************************************/ 11 | 12 | package nub.processing; 13 | 14 | import nub.core.MatrixHandler; 15 | import nub.core.Node; 16 | import nub.primitives.Matrix; 17 | import processing.core.PMatrix3D; 18 | import processing.opengl.PGraphics3D; 19 | import processing.opengl.PGraphicsOpenGL; 20 | 21 | /** 22 | * Internal {@link MatrixHandler} based on PGraphicsOpenGL graphics transformation. 23 | */ 24 | class GLMatrixHandler extends MatrixHandler { 25 | PGraphicsOpenGL _pggl; 26 | protected float[][] _matrixStackInv = new float[STACK_DEPTH][16]; 27 | 28 | public GLMatrixHandler(PGraphicsOpenGL pggl) { 29 | _pggl = pggl; 30 | } 31 | 32 | @Override 33 | public void bind(Matrix projection, Matrix view) { 34 | _bindProjection(projection); 35 | _view = view; 36 | _bindMatrix(view); 37 | } 38 | 39 | /** 40 | * Same as {@code beginHUD(_pggl.width, _pggl.height)}. 41 | */ 42 | public void beginHUD() { 43 | beginHUD(_pggl.width, _pggl.height); 44 | } 45 | 46 | @Override 47 | public void beginHUD(int width, int height) { 48 | // Otherwise Processing says: "Optimized strokes can only be disabled in 3D" 49 | if (_pggl.is3D()) 50 | _pggl.hint(_pggl.DISABLE_OPTIMIZED_STROKE); 51 | Scene.disableDepthTest(_pggl); 52 | super.beginHUD(width, height); 53 | } 54 | 55 | @Override 56 | public void endHUD() { 57 | super.endHUD(); 58 | Scene.enableDepthTest(_pggl); 59 | // Otherwise Processing says: "Optimized strokes can only be disabled in 3D" 60 | if (_pggl.is3D()) 61 | _pggl.hint(_pggl.ENABLE_OPTIMIZED_STROKE); 62 | } 63 | 64 | @Override 65 | protected void _bindProjection(Matrix matrix) { 66 | _pggl.setProjection(Scene.toPMatrix(matrix)); 67 | } 68 | 69 | @Override 70 | protected void _bindMatrix(Matrix matrix) { 71 | if (_pggl.is3D()) 72 | _pggl.setMatrix(Scene.toPMatrix(matrix));// in P5 this caches projmodelview 73 | else { 74 | _pggl.modelview.set(Scene.toPMatrix(matrix)); 75 | _pggl.projmodelview.set(Matrix.multiply(projection(), matrix).get(new float[16], false)); 76 | } 77 | } 78 | 79 | @Override 80 | public Matrix projection() { 81 | return Scene.toMatrix(_pggl.projection.get()); 82 | } 83 | 84 | @Override 85 | public Matrix model() { 86 | return Matrix.multiply(Matrix.inverse(view()), modelview()); 87 | } 88 | 89 | @Override 90 | public Matrix modelview() { 91 | return Scene.toMatrix((PMatrix3D) _pggl.getMatrix()); 92 | } 93 | 94 | @Override 95 | public void applyTransformation(Node node) { 96 | if (_pggl instanceof PGraphics3D) { 97 | translate(node.position()._vector[0], node.position()._vector[1], node.position()._vector[2]); 98 | rotate(node.orientation().angle(), (node.orientation()).axis()._vector[0], (node.orientation()).axis()._vector[1], (node.orientation()).axis()._vector[2]); 99 | scale(node.magnitude(), node.magnitude(), node.magnitude()); 100 | } else { 101 | translate(node.position().x(), node.position().y()); 102 | rotate(node.orientation().angle2D()); 103 | scale(node.magnitude(), node.magnitude()); 104 | } 105 | } 106 | 107 | @Override 108 | public void applyWorldTransformation(Node node) { 109 | Node reference = node.reference(); 110 | if (reference != null) { 111 | applyWorldTransformation(reference); 112 | applyTransformation(node); 113 | } else { 114 | applyTransformation(node); 115 | } 116 | } 117 | 118 | @Override 119 | public void pushProjection() { 120 | _pggl.pushProjection(); 121 | } 122 | 123 | @Override 124 | public void popProjection() { 125 | _pggl.popProjection(); 126 | } 127 | 128 | @Override 129 | public void applyProjection(Matrix matrix) { 130 | _pggl.applyProjection(Scene.toPMatrix(matrix)); 131 | } 132 | 133 | @Override 134 | public void pushMatrix() { 135 | if (_matrixStackDepth == STACK_DEPTH) { 136 | throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW); 137 | } 138 | _pggl.modelview.get(_matrixStack[_matrixStackDepth]); 139 | _pggl.modelviewInv.get(_matrixStackInv[_matrixStackDepth]); 140 | _matrixStackDepth++; 141 | } 142 | 143 | 144 | @Override 145 | public void popMatrix() { 146 | if (_matrixStackDepth == 0) { 147 | throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW); 148 | } 149 | _matrixStackDepth--; 150 | _pggl.modelview.set(_matrixStack[_matrixStackDepth]); 151 | _pggl.modelviewInv.set(_matrixStackInv[_matrixStackDepth]); 152 | _pggl.updateProjmodelview(); 153 | } 154 | 155 | @Override 156 | public void applyMatrix(Matrix matrix) { 157 | _pggl.applyMatrix(Scene.toPMatrix(matrix)); 158 | } 159 | 160 | @Override 161 | public void translate(float x, float y) { 162 | _pggl.translate(x, y); 163 | } 164 | 165 | @Override 166 | public void translate(float x, float y, float z) { 167 | _pggl.translate(x, y, z); 168 | } 169 | 170 | @Override 171 | public void rotate(float angle) { 172 | _pggl.rotate(angle); 173 | } 174 | 175 | @Override 176 | public void rotate(float angle, float vx, float vy, float vz) { 177 | _pggl.rotate(angle, vx, vy, vz); 178 | } 179 | 180 | @Override 181 | public void scale(float sx, float sy) { 182 | _pggl.scale(sx, sy); 183 | } 184 | 185 | @Override 186 | public void scale(float sx, float sy, float sz) { 187 | _pggl.scale(sx, sy, sz); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /style/Proscene.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /testing/data/bloom/bloom.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D texture; 2 | uniform sampler2D nuevoTex; 3 | varying vec4 vertTexCoord; 4 | 5 | void main(){ 6 | vec4 colorOriginal = vec4(0.0, 0.0, 0.0, 0.0); 7 | vec4 colorNuevo = vec4(0.0, 0.0, 0.0, 0.0); 8 | 9 | colorOriginal = texture2D(texture, vertTexCoord.st); 10 | colorNuevo = texture2D(nuevoTex, vertTexCoord.st); 11 | 12 | gl_FragColor = vec4(colorOriginal + colorNuevo); 13 | } 14 | -------------------------------------------------------------------------------- /testing/data/bloom/bloomfrag.glsl: -------------------------------------------------------------------------------- 1 | #define KERNEL_SIZE 25 2 | 3 | uniform float kernel[KERNEL_SIZE]; 4 | uniform sampler2D readTex; 5 | uniform vec2 imageIncrement; 6 | uniform vec2 resolution; 7 | 8 | //varying vec2 vUv; 9 | //varying vec2 scaledImageIncrement; 10 | varying vec4 vertTexCoord; 11 | 12 | void main() 13 | { 14 | vec2 scaledImageIncrement = imageIncrement * resolution; 15 | vec2 imageCoord = vertTexCoord.st - ( ( float(KERNEL_SIZE) - 1.0 ) / 2.0 ) * scaledImageIncrement; 16 | vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 ); 17 | 18 | for( int i = 0; i < KERNEL_SIZE; i++ ) 19 | { 20 | sum += texture2D( readTex, imageCoord ) * kernel[ i ]; 21 | imageCoord += scaledImageIncrement; 22 | } 23 | 24 | gl_FragColor = sum; 25 | } 26 | -------------------------------------------------------------------------------- /testing/data/bloom/bloomvert.glsl: -------------------------------------------------------------------------------- 1 | #define KERNEL_SIZE 25.0 2 | 3 | uniform vec2 imageIncrement; 4 | uniform vec2 resolution; 5 | uniform mat4 modelview; 6 | uniform mat4 projection; 7 | uniform mat4 texMatrix; 8 | 9 | attribute vec4 vertex; 10 | attribute vec2 texCoord; 11 | 12 | varying vec2 vUv; 13 | varying vec2 scaledImageIncrement; 14 | varying vec4 vertTexCoord; 15 | 16 | void main() 17 | { 18 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 19 | scaledImageIncrement = imageIncrement * resolution; 20 | vUv = vertTexCoord.st - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * scaledImageIncrement; 21 | gl_Position = projection * modelview * vertex; 22 | } 23 | -------------------------------------------------------------------------------- /testing/data/bloom/convfrag.glsl: -------------------------------------------------------------------------------- 1 | #define KERNEL_SIZE 25 2 | 3 | uniform float kernel[KERNEL_SIZE]; 4 | uniform sampler2D readTex; 5 | uniform vec2 imageIncrement; 6 | 7 | varying vec2 vUv; 8 | varying vec4 vertTexCoord; 9 | 10 | void main() 11 | { 12 | vec2 imageCoord = vUv - ( ( ( float(KERNEL_SIZE) - 1.0 ) / 2.0 ) * imageIncrement ); 13 | vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 ); 14 | 15 | for( int i = 0; i < KERNEL_SIZE; i++ ) 16 | { 17 | sum += texture2D( readTex, imageCoord ) * kernel[ i ]; 18 | imageCoord += imageIncrement; 19 | } 20 | 21 | gl_FragColor = sum; 22 | } 23 | -------------------------------------------------------------------------------- /testing/data/bloom/convvert.glsl: -------------------------------------------------------------------------------- 1 | #define KERNEL_SIZE 25.0 2 | 3 | uniform vec2 imageIncrement; 4 | uniform vec2 resolution; 5 | uniform mat4 modelview; 6 | uniform mat4 projection; 7 | uniform mat4 texMatrix; 8 | 9 | attribute vec4 vertex; 10 | attribute vec2 texCoord; 11 | 12 | varying vec2 vUv; 13 | varying vec2 scaledImageIncrement; 14 | varying vec4 vertTexCoord; 15 | 16 | void main() 17 | { 18 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 19 | scaledImageIncrement = imageIncrement * resolution; 20 | vUv = vertTexCoord.st - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * scaledImageIncrement; 21 | gl_Position = projection * modelview * vertex; 22 | } 23 | -------------------------------------------------------------------------------- /testing/data/bloom/noise.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D tex; 2 | 3 | varying vec4 vertexture; 4 | varying vec4 vertTexCoord; 5 | 6 | uniform float frequency; 7 | uniform float amplitude; 8 | uniform float time; 9 | uniform float speed; 10 | 11 | // 12 | // Description : Array and textureless GLSL 2D/3D/4D simplex 13 | // noise functions. 14 | // Author : Ian McEwan, Ashima Arts. 15 | // Maintainer : ijm 16 | // Lastmod : 20110822 (ijm) 17 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 18 | // Distributed under the MIT License. See LICENSE file. 19 | // https://github.com/ashima/webgl-noise 20 | // 21 | 22 | vec3 mod289(vec3 x) { 23 | return x - floor(x * (1.0 / 289.0)) * 289.0; 24 | } 25 | 26 | vec4 mod289(vec4 x) { 27 | return x - floor(x * (1.0 / 289.0)) * 289.0; 28 | } 29 | 30 | vec4 permute(vec4 x) { 31 | return mod289(((x*34.0)+1.0)*x); 32 | } 33 | 34 | vec4 taylorInvSqrt(vec4 r){ 35 | return 1.79284291400159 - 0.85373472095314 * r; 36 | } 37 | 38 | float snoise(vec3 v){ 39 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 40 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 41 | 42 | // First corner 43 | vec3 i = floor(v + dot(v, C.yyy) ); 44 | vec3 x0 = v - i + dot(i, C.xxx) ; 45 | 46 | // Other corners 47 | vec3 g = step(x0.yzx, x0.xyz); 48 | vec3 l = 1.0 - g; 49 | vec3 i1 = min( g.xyz, l.zxy ); 50 | vec3 i2 = max( g.xyz, l.zxy ); 51 | 52 | // x0 = x0 - 0.0 + 0.0 * C.xxx; 53 | // x1 = x0 - i1 + 1.0 * C.xxx; 54 | // x2 = x0 - i2 + 2.0 * C.xxx; 55 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 56 | vec3 x1 = x0 - i1 + C.xxx; 57 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 58 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 59 | 60 | // Permutations 61 | i = mod289(i); 62 | vec4 p = permute( permute( permute( 63 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 64 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 65 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 66 | 67 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 68 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 69 | float n_ = 0.142857142857; // 1.0/7.0 70 | vec3 ns = n_ * D.wyz - D.xzx; 71 | 72 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 73 | 74 | vec4 x_ = floor(j * ns.z); 75 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 76 | 77 | vec4 x = x_ *ns.x + ns.yyyy; 78 | vec4 y = y_ *ns.x + ns.yyyy; 79 | vec4 h = 1.0 - abs(x) - abs(y); 80 | 81 | vec4 b0 = vec4( x.xy, y.xy ); 82 | vec4 b1 = vec4( x.zw, y.zw ); 83 | 84 | //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 85 | //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 86 | vec4 s0 = floor(b0)*2.0 + 1.0; 87 | vec4 s1 = floor(b1)*2.0 + 1.0; 88 | vec4 sh = -step(h, vec4(0.0)); 89 | 90 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 91 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 92 | 93 | vec3 p0 = vec3(a0.xy,h.x); 94 | vec3 p1 = vec3(a0.zw,h.y); 95 | vec3 p2 = vec3(a1.xy,h.z); 96 | vec3 p3 = vec3(a1.zw,h.w); 97 | 98 | //Normalise gradients 99 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 100 | p0 *= norm.x; 101 | p1 *= norm.y; 102 | p2 *= norm.z; 103 | p3 *= norm.w; 104 | 105 | // Mix final noise value 106 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 107 | m = m * m; 108 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 109 | dot(p2,x2), dot(p3,x3) ) ); 110 | } 111 | // end of noise functions 112 | 113 | void main() 114 | { 115 | vec2 texCoords = vertTexCoord.st + vec2( 116 | amplitude * (snoise(vec3(frequency * vertTexCoord.s, frequency * vertTexCoord.t, speed * time))), 117 | amplitude * (snoise(vec3(frequency * vertTexCoord.s + 17.0, frequency * vertTexCoord.t, speed * time))) 118 | ); 119 | gl_FragColor = texture2D(tex, texCoords); 120 | } 121 | -------------------------------------------------------------------------------- /testing/data/ceva/sonia.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/testing/data/ceva/sonia.gif -------------------------------------------------------------------------------- /testing/data/depth/depth_frag.glsl: -------------------------------------------------------------------------------- 1 | // same as depth_nonlinear but packing data since it seems we need to so 2 | // (because Processing is using an old glsl version) according to: 3 | // https://forum.processing.org/two/discussion/12775/simple-shadow-mapping 4 | // "In the default shader we won't be able to access the shadowMap's depth anymore, 5 | // just the color, so this function will pack the 16bit depth float into the first 6 | // two 8bit channels of the rgba vector." 7 | 8 | vec4 packDepth(float depth) { 9 | float depthFrac = fract(depth * 255.0); 10 | return vec4(depth - depthFrac / 255.0, depthFrac, 1.0, 1.0); 11 | } 12 | 13 | void main(void) { 14 | gl_FragColor = packDepth(gl_FragCoord.z); 15 | } 16 | -------------------------------------------------------------------------------- /testing/data/depth/depth_linear.glsl: -------------------------------------------------------------------------------- 1 | // Warning: This shader is used to display the z-Buffer in a color meaningful way 2 | // To actually implement effects based on the z-Buffer use the other shader versions 3 | // The fragment eye depth is obtained by solving z_e in terms z_n from here: 4 | // http://visualcomputing.github.io/Transformations/#/7/14 and: 5 | // http://visualcomputing.github.io/Transformations/#/7/15 6 | // yielding to: z_e = (2 * near * far) / (z_n * (far - near) - far - near) (eq1) 7 | 8 | uniform float near; 9 | uniform float far; 10 | 11 | // remapping of a value among 2 ranges: http://visualcomputing.github.io/Transformations/#/7/1 12 | // same as: https://processing.org/reference/map_.html 13 | float map(float value, float start1, float stop1, float start2, float stop2) { 14 | return start2 + (value - start1) * (stop2 - start2) / (stop1 - start1); 15 | } 16 | 17 | void main() { 18 | // z_n is obtained by remapping gl_FragCoord.z from [0..1] to [-1..1] 19 | float z_n = map(gl_FragCoord.z, 0, 1, -1, 1); 20 | // eq 1 21 | float z_e = (2 * near * far) / (z_n * (far - near) - far - near); 22 | // the normalized eye depth is obtained by remapping z_e from [-near..-far] to [0..1] 23 | float depth = map(z_e, -near, -far, 0, 1); 24 | // render the depth as a grey scale color 25 | gl_FragColor = vec4(vec3(depth), 1); 26 | } 27 | -------------------------------------------------------------------------------- /testing/data/depth/depth_nonlinear.glsl: -------------------------------------------------------------------------------- 1 | // took from: https://learnopengl.com/Advanced-OpenGL/Depth-testing 2 | 3 | void main() { 4 | // gl_FragCoord.z is in the range [0..1] 5 | gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0); 6 | } -------------------------------------------------------------------------------- /testing/data/dof/depth.glsl: -------------------------------------------------------------------------------- 1 | uniform float maxDepth; 2 | 3 | void main() { 4 | float depth = gl_FragCoord.z / gl_FragCoord.w; 5 | gl_FragColor = vec4(vec3(1.0 - depth/maxDepth), 1.0); 6 | } -------------------------------------------------------------------------------- /testing/data/dof/dof.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D texture; 2 | 3 | varying vec4 vertexture; 4 | varying vec4 vertTexCoord; 5 | 6 | uniform sampler2D tDepth; 7 | 8 | uniform float maxBlur; // max blur amount 9 | uniform float aperture; // aperture - bigger values for shallower depth of field 10 | 11 | uniform float focus; 12 | uniform float aspect; 13 | 14 | void main() { 15 | vec2 vUv = vertTexCoord.st; 16 | 17 | vec2 aspectcorrect = vec2( 1.0, aspect ); 18 | 19 | vec4 depth1 = texture2D( tDepth, vUv ); 20 | 21 | float factor = depth1.x - focus; 22 | 23 | vec2 dofblur = vec2 ( clamp( factor * aperture, -maxBlur, maxBlur ) ); 24 | 25 | vec2 dofblur9 = dofblur * 0.9; 26 | vec2 dofblur7 = dofblur * 0.7; 27 | vec2 dofblur4 = dofblur * 0.4; 28 | 29 | vec4 col = vec4( 0.0 ); 30 | 31 | col += texture2D( texture, vUv.xy ); 32 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur ); 33 | col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur ); 34 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur ); 35 | col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur ); 36 | col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur ); 37 | col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur ); 38 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur ); 39 | col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur ); 40 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur ); 41 | col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur ); 42 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur ); 43 | col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur ); 44 | col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur ); 45 | col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur ); 46 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur ); 47 | col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur ); 48 | 49 | col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 ); 50 | col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 ); 51 | col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 ); 52 | col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 ); 53 | col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 ); 54 | col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 ); 55 | col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 ); 56 | col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 ); 57 | 58 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 ); 59 | col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 ); 60 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 ); 61 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 ); 62 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 ); 63 | col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 ); 64 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 ); 65 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 ); 66 | 67 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 ); 68 | col += texture2D( texture, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 ); 69 | col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 ); 70 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 ); 71 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 ); 72 | col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 ); 73 | col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 ); 74 | col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 ); 75 | 76 | gl_FragColor = col / 41.0; 77 | gl_FragColor.a = 1.0; 78 | } 79 | -------------------------------------------------------------------------------- /testing/data/globe/world32k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/testing/data/globe/world32k.jpg -------------------------------------------------------------------------------- /testing/data/interaction/rocket.mtl: -------------------------------------------------------------------------------- 1 | newmtl Default 2 | illum 2 3 | Ka 0.698039 0.698039 0.698039 4 | Kd 0.698039 0.698039 0.698039 5 | Ks 0.710000 0.710000 0.710000 6 | Ns 76.109253 7 | map_Kd rocket.png 8 | 9 | -------------------------------------------------------------------------------- /testing/data/interaction/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/testing/data/interaction/rocket.png -------------------------------------------------------------------------------- /testing/data/matrix_handler/fragment.glsl: -------------------------------------------------------------------------------- 1 | varying vec4 vertColor; 2 | 3 | void main() { 4 | gl_FragColor = vertColor; 5 | } -------------------------------------------------------------------------------- /testing/data/matrix_handler/vertex.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 nub_transform; 2 | 3 | attribute vec4 vertex; 4 | attribute vec4 color; 5 | 6 | varying vec4 vertColor; 7 | 8 | void main() { 9 | gl_Position = nub_transform * vertex; 10 | vertColor = color; 11 | } 12 | -------------------------------------------------------------------------------- /testing/data/objs/TropicalFish01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/testing/data/objs/TropicalFish01.jpg -------------------------------------------------------------------------------- /testing/data/objs/TropicalFish01.mtl: -------------------------------------------------------------------------------- 1 | # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware 2 | # File Created: 01.02.2012 21:08:55 3 | 4 | newmtl 01___Default 5 | Ns 10.0000 6 | Ni 1.5000 7 | d 1.0000 8 | Tr 0.0000 9 | Tf 1.0000 1.0000 1.0000 10 | illum 2 11 | Ka 0.5882 0.5882 0.5882 12 | Kd 0.5882 0.5882 0.5882 13 | Ks 0.0000 0.0000 0.0000 14 | Ke 0.0000 0.0000 0.0000 15 | map_Ka TropicalFish01.jpg 16 | map_Kd TropicalFish01.jpg 17 | -------------------------------------------------------------------------------- /testing/data/shadow/shadow_frag.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Used a bigger poisson disk kernel than in the tutorial to get smoother results 4 | const vec2 poissonDisk[9] = vec2[] ( 5 | vec2(0.95581, -0.18159), vec2(0.50147, -0.35807), vec2(0.69607, 0.35559), 6 | vec2(-0.0036825, -0.59150), vec2(0.15930, 0.089750), vec2(-0.65031, 0.058189), 7 | vec2(0.11915, 0.78449), vec2(-0.34296, 0.51575), vec2(-0.60380, -0.41527) 8 | ); 9 | 10 | // Unpack the 16bit depth float from the first two 8bit channels of the rgba vector 11 | float unpackDepth(vec4 color) { 12 | return color.r + color.g / 255.0; 13 | } 14 | 15 | uniform sampler2D shadowMap; 16 | varying vec4 vertColor; 17 | varying vec4 shadowCoord; 18 | varying float lightIntensity; 19 | 20 | void main(void) { 21 | // Project shadow coords, needed for a perspective light matrix (spotlight) 22 | vec3 shadowCoordProj = shadowCoord.xyz / shadowCoord.w; 23 | 24 | // Only render shadow if fragment is facing the light 25 | if(lightIntensity > 0.5) { 26 | float visibility = 9.0; 27 | // I used step() instead of branching, should be much faster this way 28 | for(int n = 0; n < 9; ++n) 29 | visibility += step(shadowCoordProj.z, unpackDepth(texture2D(shadowMap, shadowCoordProj.xy + poissonDisk[n] / 512.0))); 30 | gl_FragColor = vec4(vertColor.rgb * min(visibility * 0.05556, lightIntensity), vertColor.a); 31 | } else 32 | gl_FragColor = vec4(vertColor.rgb * lightIntensity, vertColor.a); 33 | } 34 | -------------------------------------------------------------------------------- /testing/data/shadow/shadow_nub_vert.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 nub_projection; 2 | uniform mat4 nub_view; 3 | uniform mat4 nub_model; 4 | uniform mat4 lightMatrix; 5 | uniform vec3 lightDirection; 6 | 7 | attribute vec4 vertex; 8 | attribute vec4 color; 9 | attribute vec3 normal; 10 | 11 | varying vec4 vertColor; 12 | varying vec4 shadowCoord; 13 | varying float lightIntensity; 14 | 15 | void main() { 16 | vertColor = color; 17 | // transpose(inverse(mat3(nub_model))) leads the normalMatrix 18 | vec3 vertNormal = normalize(transpose(inverse(mat3(nub_model))) * normal);// Get normal direction in world space 19 | vec4 vertPosition = nub_model * vertex; 20 | shadowCoord = lightMatrix * (vertPosition + vec4(vertNormal, 0.0));// Normal bias removes the shadow acne 21 | lightIntensity = 0.5 + dot(-lightDirection, vertNormal) * 0.5; 22 | gl_Position = nub_projection * nub_view * nub_model * vertex; 23 | } 24 | -------------------------------------------------------------------------------- /testing/data/shadow/shadow_vert.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 transform; 2 | uniform mat4 modelview; 3 | uniform mat3 normalMatrix; 4 | uniform mat4 shadowTransform; 5 | uniform vec3 lightDirection; 6 | 7 | attribute vec4 vertex; 8 | attribute vec4 color; 9 | attribute vec3 normal; 10 | 11 | varying vec4 vertColor; 12 | varying vec4 shadowCoord; 13 | varying float lightIntensity; 14 | 15 | void main() { 16 | vertColor = color; 17 | vec3 vertNormal = normalize(normalMatrix * normal);// Get normal direction in model view space 18 | vec4 vertPosition = modelview * vertex; 19 | shadowCoord = shadowTransform * (vertPosition + vec4(vertNormal, 0.0));// Normal bias removes the shadow acne 20 | lightIntensity = 0.5 + dot(-lightDirection, vertNormal) * 0.5; 21 | gl_Position = transform * vertex; 22 | } 23 | -------------------------------------------------------------------------------- /testing/data/texture/lachoy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VisualComputing/nub/06692ebd393e82768e2676533e7929c39390057c/testing/data/texture/lachoy.jpg -------------------------------------------------------------------------------- /testing/data/texture/texfrag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | precision mediump int; 4 | #endif 5 | 6 | uniform sampler2D texture; 7 | 8 | varying vec4 vertColor; 9 | varying vec4 vertTexCoord; 10 | 11 | void main() { 12 | gl_FragColor = texture2D(texture, vertTexCoord.st) * vertColor; 13 | } 14 | -------------------------------------------------------------------------------- /testing/data/texture/texvert.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 transform; 2 | uniform mat4 texMatrix; 3 | 4 | attribute vec4 position; 5 | attribute vec4 color; 6 | attribute vec2 texCoord; 7 | 8 | varying vec4 vertColor; 9 | varying vec4 vertTexCoord; 10 | 11 | void main() { 12 | gl_Position = transform * position; 13 | 14 | vertColor = color; 15 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 16 | } 17 | -------------------------------------------------------------------------------- /testing/src/AuxViewers.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.processing.Scene; 3 | import processing.core.PApplet; 4 | import processing.core.PGraphics; 5 | import processing.core.PShape; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Different ways of instantiating several viewers of the same scene 10 | */ 11 | public class AuxViewers extends PApplet { 12 | Scene scene1, scene2, scene3, focus; 13 | Node[] shapes; 14 | Node[] toruses; 15 | boolean displayAuxiliarViewers = true; 16 | // whilst scene1 is either on-screen or not; scene2 and scene3 are off-screen 17 | // test both cases here 18 | boolean onScreen = true; 19 | 20 | int w = 1920; 21 | int h = 1080; 22 | 23 | public void settings() { 24 | size(w, h, P3D); 25 | } 26 | 27 | public void setup() { 28 | scene1 = onScreen ? new Scene(g) : new Scene(createGraphics(w, h, P3D)); 29 | scene1.eye().tagging = false; 30 | shapes = new Node[15]; 31 | for (int i = 0; i < shapes.length; i++) { 32 | shapes[i] = new Node(boxShape()); 33 | shapes[i].setHUD(this::hud); 34 | shapes[i].disablePicking(Node.SHAPE); 35 | //shapes[i].enableHint(Node.BULLSEYE); 36 | //shapes[i].disablePickingMode(Node.SHAPE); 37 | scene1.randomize(shapes[i]); 38 | } 39 | toruses = new Node[15]; 40 | for (int i = 0; i < toruses.length; i++) { 41 | toruses[i] = new Node(); 42 | //toruses[i].scale(8); 43 | toruses[i].enableHint(Node.TORUS); 44 | //toruses[i].enableHint(Node.BULLSEYE); 45 | //toruses[i].disablePickingMode(Node.SHAPE); 46 | //toruses[i].setPickingPolicy(Node.SHAPE); 47 | scene1.randomize(toruses[i]); 48 | } 49 | 50 | // Note that we pass the upper left corner coordinates where the scene1 51 | // is to be drawn (see drawing code below) to its constructor. 52 | scene2 = new Scene(createGraphics(w / 2, h / 2, P3D)); 53 | scene2.eye().tagging = false; 54 | 55 | // idem here 56 | scene3 = new Scene(createGraphics(w / 2, h / 2, P3D)); 57 | scene3.eye().tagging = false; 58 | } 59 | 60 | public void hud(PGraphics pg) { 61 | pg.pushStyle(); 62 | pg.rectMode(CENTER); 63 | pg.fill(255, 0, 255, 125); 64 | pg.rect(0,0, 20, 20); 65 | pg.popStyle(); 66 | } 67 | 68 | PShape boxShape() { 69 | PShape box = createShape(BOX, 6); 70 | box.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 71 | return box; 72 | } 73 | 74 | public void keyPressed() { 75 | if (key == ' ') 76 | displayAuxiliarViewers = !displayAuxiliarViewers; 77 | if (key == 'f') 78 | focus.fit(1000); 79 | if (key == 't') { 80 | if (focus == null) 81 | return; 82 | focus.togglePerspective(); 83 | } 84 | } 85 | 86 | @Override 87 | public void mouseMoved() { 88 | if (focus == null) 89 | return; 90 | focus.tag(); 91 | } 92 | 93 | @Override 94 | public void mouseDragged() { 95 | if (focus == null) 96 | return; 97 | if (mouseButton == LEFT) 98 | focus.spin(); 99 | else if (mouseButton == RIGHT) 100 | focus.shift(); 101 | else 102 | focus.moveForward(focus.mouseDX()); 103 | } 104 | 105 | @Override 106 | public void mouseWheel(MouseEvent event) { 107 | if (focus == null) 108 | return; 109 | focus.zoom(event.getCount() * 20); 110 | } 111 | 112 | @Override 113 | public void mouseClicked(MouseEvent event) { 114 | if (focus == null) 115 | return; 116 | if (event.getCount() == 2) 117 | if (event.getButton() == LEFT) 118 | focus.focus(); 119 | else 120 | focus.align(); 121 | } 122 | 123 | public void draw() { 124 | focus = scene2.hasFocus() ? scene2 : scene3.hasFocus() ? scene3 : scene1.hasFocus() ? scene1 : null; 125 | /* 126 | scene1.openContext(); 127 | scene1.context().background(75, 25, 15); 128 | scene1.context().stroke(0, 225, 15); 129 | scene1.drawGrid(); 130 | scene1.render(); 131 | scene1.closeContext(); 132 | //scene1.render();// if offscreen, render should be forbidden after close context! 133 | scene1.image(); 134 | // */ 135 | scene1.display(color(75,25,15), false, color(0, 225, 15)); 136 | 137 | /* 138 | // works 139 | scene1.openContext(); 140 | scene1.context().background(75, 25, 15); 141 | scene1.context().stroke(0, 225, 15); 142 | scene1.drawGrid(); 143 | scene1.closeContext(); 144 | scene1.openContext(); 145 | scene1.render(); 146 | scene1.closeContext(); 147 | scene1.image(); 148 | // */ 149 | if (displayAuxiliarViewers) { 150 | scene2.openContext(); 151 | scene2.context().background(75, 25, 175); 152 | scene2.drawAxes(); 153 | scene2.render(); 154 | //scene2.image(w / 2, 0);// if there's a onscreen scene, image should be forbidden before close context! 155 | scene2.closeContext(); 156 | //scene2.render(); 157 | scene2.image(w / 2, 0); 158 | scene3.openContext(); 159 | scene3.context().background(175, 200, 20); 160 | scene3.render(); 161 | scene3.drawAxes(); 162 | //scene3.image(w / 2, h / 2);// if there's a onscreen scene, image should be forbidden before close context! 163 | scene3.closeContext(); 164 | //scene3.render(); 165 | scene3.image(w / 2, h / 2); 166 | } 167 | //println(frameRate); 168 | } 169 | 170 | public static void main(String[] args) { 171 | PApplet.main(new String[]{"AuxViewers"}); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /testing/src/BasicUse.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Quaternion; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Scene (rendering and drawing) and Node (hints) instantiation. 10 | */ 11 | public class BasicUse extends PApplet { 12 | Scene scene; 13 | Node node, child, sibling; 14 | Vector axis; 15 | 16 | //Choose P3D for a 3D scene, or P2D for a 2D one 17 | String renderer = P3D; 18 | 19 | public void settings() { 20 | size(1000, 800, renderer); 21 | } 22 | 23 | public void setup() { 24 | scene = new Scene(this, 150); 25 | scene.fit(1000); 26 | //node = new Node(); 27 | node = new Node((pg) -> { 28 | pg.pushStyle(); 29 | //pg.fill(0, 255, 255, 125); 30 | pg.fill(0, 255, 255 /*, 125*/); 31 | pg.stroke(0, 0, 255); 32 | pg.strokeWeight(2); 33 | pg.popStyle(); 34 | }); 35 | node.translate(50, 50, 50); 36 | // node.disableHint(Node.IMR); 37 | node.enableHint(Node.AXES); 38 | node.enableHint(Node.BULLSEYE); 39 | child = new Node(node); 40 | child.enableHint(Node.AXES | Node.TORUS); 41 | child.translate(-25, -75, 50); 42 | child.rotate(Quaternion.random()); 43 | //sibling = child.get(); 44 | //sibling.setReference(node); 45 | sibling = new Node(); 46 | sibling.setReference(node); 47 | sibling.set(child); 48 | //child 49 | //node.setPickingPolicy(Node.PickingPolicy.BULLS_EYE); 50 | //node.setBullsEyeSize(50); 51 | node.configHint(Node.BULLSEYE, Node.BullsEyeShape.CIRCLE); 52 | node.configHint(Node.BULLSEYE, color(0, 255, 0)); 53 | node.enableHint(Node.CAMERA, color(255, 255, 0), scene.radius() * 2); 54 | //scene.enableHint(Graph.BACKGROUND, color(100, 155, 255)); 55 | randomize(); 56 | } 57 | 58 | public void draw() { 59 | background(125); 60 | scene.render(); 61 | noStroke(); 62 | fill(0, 255, 255); 63 | scene.drawArrow(axis); 64 | } 65 | 66 | public void mouseMoved() { 67 | scene.updateTag(); 68 | } 69 | 70 | public void mouseDragged() { 71 | if (mouseButton == LEFT) 72 | scene.spin(); 73 | else if (mouseButton == RIGHT) { 74 | //Vector v = new Vector(scene.mouseDX(), 0, 0); 75 | //child.translate(v); 76 | 77 | //child.rotate(Quaternion.from(child.displacement(axis), scene.mouseRADX())); 78 | // works 79 | //sibling.rotate(Quaternion.from(sibling.displacement(axis), scene.mouseRADX())); 80 | // fails 81 | //sibling.rotate(sibling.displacement(Quaternion.from(axis, scene.mouseRADX()))); 82 | 83 | scene.turn(0.0f, scene.mouseRADX(), 0.0f); 84 | /* 85 | //scene.mouseTranslate(); 86 | //scene.rotate(0, scene.mouseRADX(), 0); 87 | Node node = scene.node(); 88 | if (node == child || node == sibling) { 89 | //Vector v = node.reference().displacement(axis); 90 | //node.rotate(Quaternion.from(v, scene.mouseRADX())); 91 | Quaternion q = Quaternion.from(axis, 0.5f * scene.mouseRADX());//node.reference().displacement(axis); 92 | node.rotate(node.reference().displacement(q)); 93 | } 94 | // */ 95 | } 96 | else 97 | scene.shift(); 98 | //scene.scale(mouseX - pmouseX); 99 | } 100 | 101 | public void mouseWheel(MouseEvent event) { 102 | if (scene.is3D()) 103 | scene.moveForward(event.getCount() * 20); 104 | else 105 | scene.zoom(event.getCount() * 20); 106 | } 107 | 108 | public void randomize() { 109 | axis = Vector.random(); 110 | axis.multiply(scene.radius() / 3); 111 | } 112 | 113 | public void keyPressed() { 114 | if (key == 'a') 115 | randomize(); 116 | if (key == ' ') 117 | node.resetHint(); 118 | if (key == '1') 119 | node.toggleHint(Node.AXES); 120 | if (key == '2') 121 | node.toggleHint(Node.CAMERA); 122 | if (key == '3') 123 | node.toggleHint(Node.BULLSEYE); 124 | if (key == '4') 125 | node.toggleHint(Node.SHAPE); 126 | //if (key == '5') 127 | //node.toggleHint(Node.FRUSTUM); 128 | if (key == '6') 129 | node.toggleHint(Node.TORUS); 130 | if (key == '7') 131 | node.toggleHint(Node.FILTER); 132 | if (key == '8') 133 | node.toggleHint(Node.BONE); 134 | 135 | if (key == 's') 136 | scene.fit(1000); 137 | if (key == 'f') 138 | scene.fit(); 139 | 140 | if (key == 'p') { 141 | println(Scene.nodes().size()); 142 | println("node hint: " + node.hint()); 143 | if (node.isHintEnabled(Node.AXES)) 144 | println("Node.AXES"); 145 | if (node.isHintEnabled(Node.CAMERA)) 146 | println("Node.CAMERA"); 147 | if (node.isHintEnabled(Node.BULLSEYE)) 148 | println("Node.BULLS_EYE"); 149 | if (node.isHintEnabled(Node.SHAPE)) 150 | println("Node.SHAPE"); 151 | //if (node.isHintEnable(Node.FRUSTUM)) 152 | //println("Node.FRUSTUM"); 153 | if (node.isHintEnabled(Node.TORUS)) 154 | println("Node.TORUS"); 155 | if (node.isHintEnabled(Node.FILTER)) 156 | println("Node.CONSTRAINT"); 157 | if (node.isHintEnabled(Node.BONE)) 158 | println("Node.BONE"); 159 | } 160 | if (key == 'r') { 161 | Quaternion q = Quaternion.random(); 162 | child.setWorldOrientation(q); 163 | /* 164 | sibling.resetReference(); 165 | sibling.setRotation(q); 166 | sibling.setReference(node); 167 | // */ 168 | sibling.setOrientation(node.displacement(q)); 169 | } 170 | } 171 | 172 | public static void main(String[] args) { 173 | PApplet.main(new String[]{"BasicUse"}); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /testing/src/CajasOrientadas.java: -------------------------------------------------------------------------------- 1 | import nub.core.Graph; 2 | import nub.core.Node; 3 | import nub.primitives.Quaternion; 4 | import nub.primitives.Vector; 5 | import nub.processing.Scene; 6 | import processing.core.PApplet; 7 | import processing.core.PGraphics; 8 | import processing.event.MouseEvent; 9 | 10 | /** 11 | * Node picking and behavior customization 12 | */ 13 | public class CajasOrientadas extends PApplet { 14 | Scene scene; 15 | Box[] cajas; 16 | Sphere esfera; 17 | boolean circle; 18 | 19 | public void settings() { 20 | size(700, 700, P3D); 21 | } 22 | 23 | public void setup() { 24 | // Set the inertia for all interactivity methods to 0.85. Default is 0.8. 25 | scene = new Scene(this, 200); 26 | scene.togglePerspective(); 27 | //scene.fit(); 28 | esfera = new Sphere(color(random(0, 255), random(0, 255), random(0, 255)), 10); 29 | esfera.setWorldPosition(new Vector(0, 1.4f, 0)); 30 | cajas = new Box[15]; 31 | for (int i = 0; i < cajas.length; i++) 32 | cajas[i] = new Box(color(random(0, 255), random(0, 255), random(0, 255)), 33 | random(10, 40), random(10, 40), random(10, 40)); 34 | scene.tag("keyboard", esfera); 35 | } 36 | 37 | public void draw() { 38 | background(0); 39 | scene.render(); 40 | } 41 | 42 | public void mouseClicked() { 43 | scene.focus(); 44 | } 45 | 46 | public void mouseMoved() { 47 | scene.tag(); 48 | } 49 | 50 | public void mouseDragged() { 51 | if (mouseButton == LEFT) 52 | scene.spin(); 53 | else if (mouseButton == RIGHT) 54 | scene.shift(); 55 | else 56 | scene.zoom(mouseX - pmouseX); 57 | } 58 | 59 | public void mouseWheel(MouseEvent event) { 60 | scene.moveForward(event.getCount() * 20); 61 | } 62 | 63 | public void keyPressed() { 64 | if (key == ' ') 65 | for (Box caja : cajas) { 66 | caja.toggleHint(Node.BULLSEYE); 67 | caja.togglePicking(Node.SHAPE); 68 | } 69 | if (key == 'c') { 70 | for (Box caja : cajas) 71 | if (caja.bullsEyeSize() < 1) 72 | caja.setBullsEyeSize(caja.bullsEyeSize() * 200); 73 | else 74 | caja.setBullsEyeSize(caja.bullsEyeSize() / 200); 75 | } 76 | if (key == 'd') { 77 | circle = !circle; 78 | for (Box caja : cajas) 79 | caja.configHint(Node.BULLSEYE, circle ? Node.BullsEyeShape.CIRCLE : Node.BullsEyeShape.SQUARE); 80 | } 81 | if (key == 'a') 82 | for (Box caja : cajas) 83 | caja.toggleHint(Node.AXES); 84 | if (key == 'p') 85 | for (Box caja : cajas) 86 | caja.toggleHint(Node.BULLSEYE); 87 | if (key == 'e') 88 | scene.togglePerspective(); 89 | if (key == 's') 90 | scene.fit(1000); 91 | if (key == 'S') 92 | scene.fit(); 93 | if (key == 'u') 94 | if (scene.isTagValid("keyboard")) 95 | scene.removeTag("keyboard"); 96 | else 97 | scene.tag("keyboard", esfera); 98 | if (key == CODED) 99 | if (keyCode == UP) 100 | scene.shift("keyboard", 0, -10, 0); 101 | else if (keyCode == DOWN) 102 | scene.shift("keyboard", 0, 10, 0); 103 | else if (keyCode == LEFT) 104 | scene.shift("keyboard", -10, 0, 0); 105 | else if (keyCode == RIGHT) 106 | scene.shift("keyboard", 10, 0, 0); 107 | } 108 | 109 | public class Box extends Node { 110 | float _w, _h, _d; 111 | int _color; 112 | 113 | public Box(int tint, float w, float h, float d) { 114 | setShape(this::caja); 115 | setBehavior(scene, this::behavior); 116 | _color = tint; 117 | _w = w; 118 | _h = h; 119 | _d = d; 120 | setBullsEyeSize(max(_w, _h, _d) / scene.radius()); 121 | scene.randomize(this); 122 | enableHint(Node.AXES); 123 | } 124 | 125 | // geometry is defined at the node local coordinate system 126 | public void caja(PGraphics pg) { 127 | pg.pushStyle(); 128 | pg.noStroke(); 129 | pg.fill(_color); 130 | pg.box(_w, _h, _d); 131 | pg.popStyle(); 132 | } 133 | 134 | public void behavior(Graph graph) { 135 | Vector to = Vector.subtract(esfera.worldPosition(), worldPosition()); 136 | setWorldOrientation(Quaternion.from(Vector.plusJ, to)); 137 | } 138 | } 139 | 140 | class Sphere extends Node { 141 | float _radius; 142 | int _color; 143 | 144 | public Sphere(int tint, float radius) { 145 | _color = tint; 146 | _radius = radius; 147 | setShape((PGraphics pg) -> { 148 | pg.pushStyle(); 149 | pg.noStroke(); 150 | pg.fill(_color); 151 | pg.sphere(_radius); 152 | pg.popStyle(); 153 | }); 154 | } 155 | } 156 | 157 | public static void main(String[] args) { 158 | PApplet.main(new String[]{"CajasOrientadas"}); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /testing/src/CustomNodeInteraction.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.processing.Scene; 3 | import processing.core.PApplet; 4 | import processing.core.PFont; 5 | import processing.core.PGraphics; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Node interaction customization 10 | */ 11 | public class CustomNodeInteraction extends PApplet { 12 | Scene scene; 13 | Torus[] shapes; 14 | PFont font36; 15 | int totalShapes; 16 | 17 | //Choose P2D or P3D 18 | String renderer = P3D; 19 | 20 | public void settings() { 21 | size(1200, 700, renderer); 22 | } 23 | 24 | public void setup() { 25 | font36 = loadFont("FreeSans-36.vlw"); 26 | scene = new Scene(this); 27 | scene.fit(1000); 28 | shapes = new Torus[10]; 29 | for (int i = 0; i < shapes.length; i++) { 30 | shapes[i] = new Torus(); 31 | } 32 | } 33 | 34 | public void draw() { 35 | background(0); 36 | scene.render(); 37 | } 38 | 39 | public void keyPressed() { 40 | int value = Character.getNumericValue(key); 41 | if (value >= 0 && value < 10) 42 | scene.tag(shapes[value].node); 43 | if (key == ' ') 44 | scene.removeTag(); 45 | if (key == CODED) 46 | if (keyCode == UP) 47 | scene.shift(0, -10, 0); 48 | else if (keyCode == DOWN) 49 | scene.shift(0, 10, 0); 50 | else if (keyCode == LEFT) 51 | scene.interact( "menos"); 52 | else if (keyCode == RIGHT) 53 | scene.interact("mas"); 54 | } 55 | 56 | public void mouseDragged() { 57 | if (mouseButton == LEFT) 58 | scene.spin(); 59 | else if (mouseButton == CENTER) 60 | scene.zoom(scene.mouseDX()); 61 | else 62 | scene.shift(); 63 | } 64 | 65 | public void mouseWheel(MouseEvent event) { 66 | scene.interact(event.getCount()); 67 | } 68 | 69 | public void mouseClicked(MouseEvent event) { 70 | if (event.getCount() == 1) 71 | scene.interact(); 72 | if (event.getCount() == 2) 73 | scene.tag(); 74 | } 75 | 76 | public class Torus { 77 | int id = totalShapes++, faces = randomFaces(), colour = randomColor(); 78 | Node node; 79 | 80 | Torus() { 81 | node = new Node(); 82 | node.enableHint(Node.TORUS, colour, faces); 83 | node.setInteraction(this::interact); 84 | node.setHUD(this::hud); 85 | scene.randomize(node); 86 | } 87 | 88 | void hud(PGraphics pg) { 89 | pg.fill(node.isTagged(scene) ? 0 : 255, node.isTagged(scene) ? 255 : 0, node.isTagged(scene) ? 0 : 255); 90 | pg.textFont(font36); 91 | pg.text(id, 0, 0); 92 | } 93 | 94 | void interact(Object[] gesture) { 95 | if (gesture.length == 0){ 96 | colour = randomColor(); 97 | node.configHint(Node.TORUS, colour, faces); 98 | } 99 | if (gesture.length == 1) { 100 | if (gesture[0] instanceof String) { 101 | if (((String) gesture[0]).matches("mas")) 102 | faces++; 103 | else if (((String) gesture[0]).matches("menos")) 104 | if (faces > 2) 105 | faces--; 106 | } else if (gesture[0] instanceof Integer) { 107 | int delta = (Integer) gesture[0]; 108 | if (faces + delta > 1) 109 | faces = faces + delta; 110 | } 111 | node.configHint(Node.TORUS, colour, faces); 112 | } 113 | } 114 | 115 | int randomColor() { 116 | return color(random(255), random(255), random(255), random(125, 255)); 117 | } 118 | 119 | int randomFaces() { 120 | return (int) random(3, 15); 121 | } 122 | } 123 | 124 | public static void main(String[] args) { 125 | PApplet.main(new String[]{"CustomNodeInteraction"}); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /testing/src/DOF.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.processing.Scene; 3 | import processing.core.PApplet; 4 | import processing.core.PGraphics; 5 | import processing.core.PShape; 6 | import processing.event.MouseEvent; 7 | import processing.opengl.PShader; 8 | 9 | import java.nio.file.Paths; 10 | 11 | /** 12 | * Depth-Of-Filed (DOF) post-processing effect 13 | * https://t.ly/-ADs 14 | */ 15 | public class DOF extends PApplet { 16 | String depthPath; 17 | PShader depthShader, dofShader; 18 | PGraphics dofPGraphics; 19 | Scene scene, depthScene; 20 | Node[] models; 21 | int mode = 2; 22 | boolean exact = true; 23 | 24 | @Override 25 | public void settings() { 26 | size(1400, 1400, P3D); 27 | } 28 | 29 | @Override 30 | public void setup() { 31 | scene = new Scene(createGraphics(width, height, P3D), 1000); 32 | scene.fit(1000); 33 | models = new Node[100]; 34 | for (int i = 0; i < models.length; i++) { 35 | models[i] = new Node(boxShape()); 36 | //models[i].setBullsEyeSize(0.7f); 37 | scene.randomize(models[i]); 38 | } 39 | // Depth shader 40 | // Test all the different versions 41 | depthPath = Paths.get("testing/data/depth/depth_linear.glsl").toAbsolutePath().toString(); 42 | //depthPath = Paths.get("testing/data/depth/depth_nonlinear.glsl").toAbsolutePath().toString(); 43 | //depthPath = Paths.get("testing/data/depth/depth_frag.glsl").toAbsolutePath().toString(); 44 | depthShader = loadShader(depthPath); 45 | // TODO add proper constructor to share eye node 46 | depthScene = new Scene(createGraphics(width, height, P3D), scene.eye(), 1000); 47 | //depthScene.fit(); 48 | depthScene.context().shader(depthShader); 49 | // TODO make API more consistent 50 | depthScene.picking = false; 51 | // DOF shader 52 | dofShader = loadShader(Paths.get("testing/data/dof/dof.glsl").toAbsolutePath().toString()); 53 | dofShader.set("aspect", width / (float) height); 54 | dofShader.set("maxBlur", (float) 0.015); 55 | dofShader.set("aperture", (float) 0.02); 56 | dofPGraphics = createGraphics(width, height, P3D); 57 | dofPGraphics.shader(dofShader); 58 | 59 | frameRate(1000); 60 | } 61 | 62 | @Override 63 | public void draw() { 64 | // 1. Render into main buffer 65 | scene.openContext(); 66 | scene.context().background(0); 67 | scene.render(); 68 | scene.closeContext(); 69 | // 2. Draw into depth buffer 70 | depthScene.openContext(); 71 | depthScene.context().background(0); 72 | depthShader.set("near", depthScene.zNear()); 73 | depthShader.set("far", depthScene.zFar()); 74 | depthScene.render(); 75 | depthScene.closeContext(); 76 | // 3. Draw destination buffer 77 | dofPGraphics.beginDraw(); 78 | dofShader.set("focus", map(mouseX, 0, width, -0.5f, 1.5f)); 79 | dofShader.set("tDepth", depthScene.context()); 80 | dofPGraphics.image(scene.context(), 0, 0); 81 | dofPGraphics.endDraw(); 82 | // display one of the 3 buffers 83 | if (mode == 0) 84 | scene.image(); 85 | else if (mode == 1) 86 | depthScene.image(); 87 | //image(depthScene.context(), 0, 0); 88 | else 89 | image(dofPGraphics, 0, 0); 90 | // println("-> frameRate: " + Scene.TimingHandler.frameRate + " (nub) " + frameRate + " (p5)"); 91 | } 92 | 93 | PShape boxShape() { 94 | PShape box = createShape(BOX, 60); 95 | box.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 96 | return box; 97 | } 98 | 99 | @Override 100 | public void keyPressed() { 101 | if (key == '0') mode = 0; 102 | if (key == '1') mode = 1; 103 | if (key == '2') mode = 2; 104 | if (key == 't') 105 | scene.togglePerspective(); 106 | if (key == 'f') 107 | scene.fit(1000); 108 | if (key == 'F') 109 | scene.fit(); 110 | } 111 | 112 | @Override 113 | public void mouseMoved() { 114 | scene.tag(); 115 | } 116 | 117 | @Override 118 | public void mouseDragged() { 119 | if (mouseButton == LEFT) 120 | scene.spin(); 121 | else if (mouseButton == RIGHT) 122 | scene.shift(); 123 | else 124 | scene.moveForward(scene.mouseDX()); 125 | } 126 | 127 | @Override 128 | public void mouseWheel(MouseEvent event) { 129 | scene.zoom(event.getCount() * 20); 130 | } 131 | 132 | @Override 133 | public void mouseClicked(MouseEvent event) { 134 | if (event.getCount() == 2) 135 | if (event.getButton() == LEFT) 136 | scene.focus(); 137 | else 138 | scene.align(); 139 | } 140 | 141 | public static void main(String[] args) { 142 | PApplet.main(new String[]{"DOF"}); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /testing/src/DepthMap.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Quaternion; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.core.PGraphics; 7 | import processing.event.MouseEvent; 8 | import processing.opengl.PShader; 9 | 10 | import java.nio.file.Paths; 11 | 12 | /** 13 | * Depth map shader useful for DOF and other post-processing effects 14 | * https://t.ly/0Qea 15 | */ 16 | public class DepthMap extends PApplet { 17 | Scene scene; 18 | Scene depthMapScene; 19 | Node[] shapes; 20 | PGraphics depthMap; 21 | PShader depthShader; 22 | float zNear = 50; 23 | float zFar = 700; 24 | int w = 1400; 25 | int h = 1400; 26 | 27 | public void settings() { 28 | size(w, h, P3D); 29 | } 30 | 31 | public void setup() { 32 | depthMap = createGraphics(w / 2, h / 2, P3D); 33 | depthShader = loadShader(Paths.get("testing/data/depth/depth_linear.glsl").toAbsolutePath().toString()); 34 | depthShader.set("near", zNear); 35 | depthShader.set("far", zFar); 36 | depthMap.shader(depthShader); 37 | scene = new Scene(this, max(w, h)); 38 | scene.fit(1000); 39 | shapes = new Node[20]; 40 | for (int i = 0; i < shapes.length; i++) { 41 | shapes[i] = new Node(this::cube); 42 | scene.randomize(shapes[i]); 43 | shapes[i].setHighlight(0); 44 | } 45 | scene.tag("light", shapes[(int) random(0, shapes.length - 1)]); 46 | scene.node("light").toggleHint(Node.SHAPE | Node.AXES | Node.BOUNDS); 47 | scene.node("light").setWorldOrientation(Quaternion.from(Vector.plusK, scene.node("light").worldPosition())); 48 | // scene.enablePicking(false); 49 | depthMapScene = new Scene(depthMap, scene.node("light")); 50 | depthMapScene.setZNear(() -> zNear); 51 | depthMapScene.setZFar(() -> zFar); 52 | depthMapScene.togglePerspective(); 53 | depthMapScene.picking = false; 54 | frameRate(1000); 55 | } 56 | 57 | public void cube(PGraphics pg) { 58 | pg.pushStyle(); 59 | if (pg == depthMap) 60 | pg.noStroke(); 61 | else { 62 | pg.strokeWeight(3); 63 | pg.stroke(0, 255, 255); 64 | } 65 | pg.fill(255, 0, 0); 66 | pg.box(80); 67 | pg.popStyle(); 68 | } 69 | 70 | public void draw() { 71 | // 1. Fill in and display front-buffer 72 | background(75, 25, 15); 73 | scene.render(); 74 | // 2. Fill in shadow map using the light point of view 75 | if (scene.isTagValid("light")) { 76 | depthMapScene.openContext(); 77 | depthMapScene.context().background(140, 160, 125); 78 | depthMapScene.drawAxes(); 79 | depthMapScene.render(); 80 | depthMapScene.closeContext(); 81 | depthMapScene.image(w / 2, h / 2); 82 | } 83 | } 84 | 85 | public void mouseMoved(MouseEvent event) { 86 | if (event.isShiftDown()) { 87 | if (scene.isTagValid("light")) { 88 | scene.node("light").toggleHint(Node.SHAPE | Node.AXES | Node.BOUNDS); 89 | } 90 | // no calling mouseTag since we need to immediately update the tagged node 91 | scene.updateTag("light"); 92 | if (scene.isTagValid("light")) { 93 | depthMapScene.setEye(scene.node("light")); 94 | scene.node("light").toggleHint(Node.SHAPE | Node.AXES | Node.BOUNDS); 95 | } 96 | } else 97 | scene.tag(); 98 | } 99 | 100 | public void mouseDragged() { 101 | if (mouseButton == LEFT) 102 | scene.spin(); 103 | else if (mouseButton == RIGHT) 104 | scene.shift(); 105 | else 106 | scene.moveForward(mouseX - pmouseX); 107 | } 108 | 109 | public void mouseWheel(MouseEvent event) { 110 | if (event.isShiftDown() && scene.isTagValid("light")) { 111 | depthShader.set("far", zFar += event.getCount() * 20); 112 | depthMapScene.setZFar(() -> zFar); 113 | } 114 | else 115 | scene.zoom(event.getCount() * 20); 116 | } 117 | 118 | public void keyPressed() { 119 | if (key == ' ' && scene.isTagValid("light")) { 120 | depthMapScene.togglePerspective(); 121 | } 122 | if (key == 'p') 123 | scene.togglePerspective(); 124 | } 125 | 126 | public static void main(String[] args) { 127 | PApplet.main(new String[]{"DepthMap"}); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /testing/src/GraphAPI.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Matrix; 3 | import nub.processing.Scene; 4 | import processing.core.PApplet; 5 | import processing.core.PShape; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Thorough graph api test based upon the following graph: 10 | * 1: red; 2: green; 3: blue; 4: yellow; 5: magenta; detached1: cyan; detached2:grey 11 | * World 12 | * ^ 13 | * |\ 14 | * 1 eye 15 | * ^ 16 | * |\ 17 | * 2 3 18 | * | 19 | * 4 20 | * | 21 | * 5 22 | */ 23 | public class GraphAPI extends PApplet { 24 | Scene scene; 25 | Node n1, n2, n3, n4, n5, detached1, detached2, clone; 26 | 27 | //Choose FX2D, JAVA2D, P2D or P3D 28 | String renderer = P3D; 29 | 30 | public void settings() { 31 | size(900, 900, renderer); 32 | } 33 | 34 | public void setup() { 35 | scene = new Scene(this); 36 | 37 | // red 38 | n1 = new Node(shape(color(255, 0, 0, 125))); 39 | 40 | // green 41 | n2 = new Node(n1, shape(color(0, 255, 0, 125))); 42 | scene.randomize(n2); 43 | n2.scale(0.5f); 44 | 45 | // blue 46 | n3 = new Node(n1, shape(color(0, 0, 255, 125))); 47 | scene.randomize(n3); 48 | 49 | // yellow 50 | n4 = new Node(n2, shape(color(255, 255, 0, 125))); 51 | scene.randomize(n4); 52 | 53 | // magenta 54 | n5 = new Node(n4, shape(color(255, 0, 255, 125))); 55 | scene.randomize(n5); 56 | 57 | // cyan 58 | //detached1 = new Node(); 59 | //Graph.detach(detached1); 60 | // same as two prev lines 61 | detached1 = new Node(false); 62 | detached1.set(n3); 63 | detached1.setShape(shape(color(0, 255, 255, 125))); 64 | 65 | // grey 66 | detached2 = new Node(false); 67 | detached2.setShape(shape(color(125, 125))); 68 | 69 | float dx = -10; 70 | float dy = 15; 71 | float dz = 5; 72 | Matrix t = new Matrix(1, 0, 0, 0, 73 | 0, 1, 0, 0, 74 | 0, 0, 1, 0, 75 | dx, dy, dz, 0); 76 | float b = QUARTER_PI; 77 | Matrix r = new Matrix(cos(b), sin(b), 0, 0, 78 | -sin(b), cos(b), 0, 0, 79 | 0, 0, 1, 0, 80 | 0, 0, 0, 1); 81 | println(t.toString()); 82 | println(r.toString()); 83 | println(Matrix.multiply(t, r).toString()); 84 | t.rotateZ(b); 85 | println(t.toString()); 86 | } 87 | 88 | PShape shape(int c) { 89 | PShape pShape = createShape(BOX, 30); 90 | pShape.setFill(c); 91 | return pShape; 92 | } 93 | 94 | public void draw() { 95 | background(125); 96 | scene.render(); 97 | scene.drawAxes(); 98 | } 99 | 100 | public void keyPressed() { 101 | if (key == 'c') { 102 | clone = n5.copy(); 103 | clone.resetHint(); 104 | clone.enableHint(Node.TORUS); 105 | n5.resetHint(); 106 | n5.enableHint(Node.AXES); 107 | } 108 | if (key == '1') { 109 | n4.setReference(n3); 110 | } 111 | if (key == '2') { 112 | detached1.setReference(n2); 113 | } 114 | if (key == '3') { 115 | n2.setReference(detached1); 116 | } 117 | if (key == '4') { 118 | detached2.setReference(detached1); 119 | } 120 | if (key == '5') { 121 | if (detached1 != null) 122 | detached1.attach(); 123 | } 124 | if (key == '6') { 125 | if (detached2 != null) 126 | detached2.attach(); 127 | } 128 | if (key == '7') { 129 | n2.copy(); 130 | } 131 | if (key == '8') { 132 | n2.detach(); 133 | } 134 | if (key == '9') { 135 | detached1.detach(); 136 | } 137 | } 138 | 139 | @Override 140 | public void mouseMoved() { 141 | scene.tag(); 142 | } 143 | 144 | @Override 145 | public void mouseDragged() { 146 | if (mouseButton == LEFT) 147 | scene.spin(); 148 | else if (mouseButton == RIGHT) 149 | scene.shift(); 150 | else 151 | scene.moveForward(mouseX - pmouseX); 152 | } 153 | 154 | @Override 155 | public void mouseWheel(MouseEvent event) { 156 | scene.zoom(event.getCount() * 20); 157 | } 158 | 159 | @Override 160 | public void mouseClicked(MouseEvent event) { 161 | if (event.getCount() == 2) 162 | if (event.getButton() == LEFT) 163 | scene.focus(); 164 | else 165 | scene.align(); 166 | } 167 | 168 | public static void main(String[] args) { 169 | PApplet.main(new String[]{"GraphAPI"}); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /testing/src/Interpolators.java: -------------------------------------------------------------------------------- 1 | import nub.core.Graph; 2 | import nub.core.Node; 3 | import nub.processing.Scene; 4 | import processing.core.PApplet; 5 | import processing.core.PGraphics; 6 | import processing.core.PShape; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * This example introduces the three different interpolations offered by the Graph. 11 | */ 12 | public class Interpolators extends PApplet { 13 | Scene scene; 14 | Node shape; 15 | boolean recurrent = true; 16 | 17 | //Choose P3D or P2D 18 | String renderer = P3D; 19 | 20 | public void settings() { 21 | size(1920, 1080, renderer); 22 | } 23 | 24 | public void setup() { 25 | //scene = new Scene(this, 150); 26 | scene = new Scene(createGraphics(1920, 1080, P3D), 150); 27 | scene.eye().enableHint(Node.KEYFRAMES); 28 | PShape pshape; 29 | if (scene.is2D()) { 30 | rectMode(CENTER); 31 | pshape = createShape(RECT, 0, 0, 100, 100); 32 | } 33 | else { 34 | pshape = createShape(BOX, 30); 35 | } 36 | pshape.setFill(color(0, 255, 255/*, 125*/)); 37 | shape = new Node(pshape); 38 | shape.setAnimationRecurrence(recurrent); 39 | shape.setMinMaxScalingFilter(0.8f, 1.2f); 40 | shape.setHUD(this::hud); 41 | shape.enableHint(Node.AXES); 42 | shape.enableHint(Node.BULLSEYE); 43 | shape.enableHint(Node.KEYFRAMES, Node.AXES | Node.BULLSEYE, 2, color(0, 255, 0), 10); 44 | shape.configHint(Node.BULLSEYE, color(255, 0, 0)); 45 | shape.setBullsEyeSize(50); 46 | int count = (int) random(4, 10); 47 | count = 10; 48 | for (int i = 0; i < count; i++) { 49 | //shape.addKeyFrame(scene.randomNode(), i % 2 == 1 ? 1000 : 4000); 50 | /* 51 | Node node = scene.randomNode(); 52 | node.enableHint(Node.BULLSEYE); 53 | shape.addKeyFrame(node, i % 2 == 1 ? 1000 : 4000); 54 | // */ 55 | // /* 56 | scene.randomize(shape); 57 | shape.addKeyFrame(Node.AXES | Node.SHAPE, i % 2 == 1 ? 1000 : 4000); 58 | // */ 59 | } 60 | shape.resetScalingFilter(); 61 | shape.animate(); 62 | frameRate(1000); 63 | } 64 | 65 | public void draw() { 66 | /* 67 | // WARNING: works only for onscreen scenes 68 | background(125); 69 | scene.render(); 70 | scene.drawAxes(); 71 | stroke(0,255,0); 72 | scene.drawGrid(); 73 | scene.beginHUD(); 74 | hud(scene.context()); 75 | scene.endHUD(); 76 | // */ 77 | // /* 78 | // Works for both onscreen and offscreen scenes!!! 79 | scene.display(color(125), true, color(0, 255, 0)/*, this::sceneHUD*/); 80 | //scene.display(color(125), true, true, this::customBox); 81 | // */ 82 | } 83 | 84 | public void customBox() { 85 | PGraphics pg = scene.context(); 86 | pg.pushStyle(); 87 | // /* 88 | pg.fill(255, 0, 0, 125); 89 | pg.box(30); 90 | // */ 91 | // pg.shape(box); 92 | pg.popStyle(); 93 | } 94 | 95 | public void sceneHUD() { 96 | scene.beginHUD(); 97 | hud(scene.context()); 98 | scene.endHUD(); 99 | } 100 | 101 | public void hud(PGraphics pg) { 102 | pg.pushStyle(); 103 | pg.rectMode(CENTER); 104 | pg.fill(255, 0, 255, 125); 105 | pg.stroke(0,0,255); 106 | pg.strokeWeight(3); 107 | pg.rect(0, 0, 80, 50); 108 | pg.popStyle(); 109 | } 110 | 111 | public void mouseMoved() { 112 | scene.updateTag(); 113 | } 114 | 115 | public void mouseDragged() { 116 | if (mouseButton == LEFT) 117 | scene.spin(); 118 | else if (mouseButton == RIGHT) 119 | scene.shift(); 120 | else 121 | scene.moveForward((mouseX - pmouseX)/5); 122 | } 123 | 124 | public void mouseWheel(MouseEvent event) { 125 | if (scene.is3D()) 126 | scene.moveForward(event.getCount() * 20); 127 | else 128 | scene.zoom(event.getCount() * 20); 129 | } 130 | 131 | float speed = 1; 132 | 133 | public void keyPressed() { 134 | if (key == 'm') { 135 | shape.animate(-1); 136 | } 137 | if (key == 'n') { 138 | recurrent = !recurrent; 139 | shape.setAnimationRecurrence(recurrent); 140 | } 141 | if (key == 'q') { 142 | shape.resetAnimation(); 143 | } 144 | if (key == 'y') { 145 | if (shape.isAttached()) 146 | shape.detach(); 147 | else 148 | shape.attach(); 149 | } 150 | if (key == 'x') 151 | shape.removeKeyFrames(); 152 | if (key == 'c') { 153 | println(Graph.nodes().size()); 154 | shape.removeKeyFrame(1); 155 | println(Graph.nodes().size()); 156 | } 157 | if (key == 't') { 158 | shape.setAnimationTime(23250); 159 | } 160 | if (key == 'z') { 161 | println(scene.fov()); 162 | println(scene.eye().worldMagnitude()); 163 | } 164 | if (key == ' ') { 165 | shape.toggleHint(Node.KEYFRAMES); 166 | scene.eye().toggleHint(Node.KEYFRAMES); 167 | } 168 | if (key == 'r') { 169 | shape.removeKeyFrame(3); 170 | } 171 | if (key == 'p') { 172 | shape.toggleAnimation(); 173 | } 174 | if (key == '-' || key == '+') { 175 | shape.animate(speed += key == '+' ? 0.25f : -0.25f); 176 | } 177 | 178 | if (key == '1') { 179 | scene.eye().addKeyFrame(Node.CAMERA | Node.BULLSEYE, 1000); 180 | } 181 | if (key == 'a') 182 | scene.eye().toggleAnimation(); 183 | if (key == 'b') 184 | scene.eye().removeKeyFrames(); 185 | 186 | if (key == 's') 187 | scene.fit(1000); 188 | if (key == 'f') 189 | scene.fit(); 190 | } 191 | 192 | public static void main(String[] args) { 193 | PApplet.main(new String[]{"Interpolators"}); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /testing/src/Luxo.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Quaternion; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.core.PGraphics; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * Pixar luxo (https://t.ly/9mKG6) graph with node filters 11 | */ 12 | public class Luxo extends PApplet { 13 | Scene scene; 14 | Node floor, base, arm, forarm, shade; 15 | 16 | public void settings() { 17 | size(1000, 700, P3D); 18 | } 19 | 20 | public void setup() { 21 | scene = new Scene(this); 22 | //scene.setShape(this::floor); 23 | scene.fit(1000); 24 | base = new Node(this::base); 25 | base.setTranslationFilter(Node.translationPlaneFilter, new Object[] { Vector.plusK }); 26 | base.setRotationFilter(Node.rotationAxisFilter, new Object[] { Vector.plusK }); 27 | arm = new Node(base, this::limb); 28 | arm.setPosition(0, 0, 8); 29 | arm.setOrientation(Quaternion.from(Vector.plusI, 0.6)); 30 | arm.setRotationFilter(Node.rotationAxisFilter, new Object[] { Vector.plusI }); 31 | forarm = new Node(arm, this::limb); 32 | forarm.setPosition(0, 0, 50); 33 | forarm.setOrientation(Quaternion.from(Vector.plusI, -2)); 34 | forarm.setRotationFilter(Node.rotationAxisFilter, new Object[] { Vector.plusI }); 35 | shade = new Node(forarm, this::shade); 36 | shade.setPosition(0, 0, 50); 37 | shade.setOrientation(Quaternion.from(new Vector(1, -0.3f, 0), -1.7)); 38 | // for the lights to work the floor node should be the last to be added 39 | floor = new Node(this::floor); 40 | floor.tagging = false; 41 | } 42 | 43 | void cone(PGraphics pg, float zMin, float zMax, float r1, float r2, int nbSub) { 44 | pg.pushStyle(); 45 | pg.noStroke(); 46 | pg.translate(0, 0, zMin); 47 | Scene.drawCone(pg, nbSub, 0, 0, r1, r2, zMax - zMin); 48 | pg.translate(0, 0, -zMin); 49 | pg.popStyle(); 50 | } 51 | 52 | void base(PGraphics pg) { 53 | pg.pushStyle(); 54 | pg.fill(0, 0, 255); 55 | cone(pg, 0, 3, 15, 15, 30); 56 | cone(pg, 3, 5, 15, 13, 30); 57 | cone(pg, 5, 7, 13, 1, 30); 58 | cone(pg, 7, 9, 1, 1, 10); 59 | pg.popStyle(); 60 | } 61 | 62 | void limb(PGraphics pg) { 63 | pg.pushStyle(); 64 | pg.pushMatrix(); 65 | pg.rotate(HALF_PI, 0, 1, 0); 66 | cone(pg, -5, 5, 2, 2, 20); 67 | pg.popMatrix(); 68 | pg.translate(2, 0, 0); 69 | cone(pg, 0, 50, 1, 1, 10); 70 | pg.translate(-4, 0, 0); 71 | cone(pg, 0, 50, 1, 1, 10); 72 | pg.translate(2, 0, 0); 73 | pg.popStyle(); 74 | } 75 | 76 | void shade(PGraphics pg) { 77 | pg.pushStyle(); 78 | pg.fill(0, 255, 255); 79 | cone(pg, -2, 6, 4, 4, 30); 80 | cone(pg, 6, 15, 4, 17, 30); 81 | cone(pg, 15, 17, 17, 17, 30); 82 | pg.spotLight(155, 255, 255, 0, 0, 0, 0, 0, 1, THIRD_PI, 1); 83 | pg.popStyle(); 84 | } 85 | 86 | void floor(PGraphics pg) { 87 | pg.pushStyle(); 88 | pg.noStroke(); 89 | pg.fill(120, 120, 120); 90 | float nbPatches = 100; 91 | pg.normal(0, 0, 1); 92 | for (int j = 0; j < nbPatches; ++j) { 93 | pg.beginShape(QUAD_STRIP); 94 | for (int i = 0; i <= nbPatches; ++i) { 95 | pg.vertex((200 * (float) i / nbPatches - 100), (200 * j / nbPatches - 100)); 96 | pg.vertex((200 * (float) i / nbPatches - 100), (200 * (float) (j + 1) / nbPatches - 100)); 97 | } 98 | pg.endShape(); 99 | } 100 | pg.popStyle(); 101 | } 102 | 103 | public void draw() { 104 | background(0); 105 | lights(); 106 | scene.render(); 107 | } 108 | 109 | public void mouseMoved() { 110 | scene.tag(); 111 | } 112 | 113 | public void mouseDragged() { 114 | if (mouseButton == LEFT) 115 | scene.spin(); 116 | else if (mouseButton == RIGHT) { 117 | if (scene.node() == base || scene.node() == null) 118 | scene.shift(); 119 | } 120 | else 121 | scene.zoom(mouseX - pmouseX); 122 | } 123 | 124 | public void mouseWheel(MouseEvent event) { 125 | scene.moveForward(event.getCount() * 20); 126 | } 127 | 128 | public static void main(String[] args) { 129 | PApplet.main(new String[]{"Luxo"}); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /testing/src/MiniMap.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.processing.Scene; 3 | import processing.core.PApplet; 4 | import processing.core.PShape; 5 | import processing.event.MouseEvent; 6 | 7 | /** 8 | * 2D and 3D minimaps 9 | * https://t.ly/oDHL 10 | */ 11 | public class MiniMap extends PApplet { 12 | Scene scene, minimap, focus; 13 | Node[] models; 14 | boolean displayMinimap = true; 15 | // whilst scene is either on-screen or not, the minimap is always off-screen 16 | // test both cases here: 17 | boolean onScreen = false; 18 | boolean interactiveEye; 19 | 20 | int w = 1920; 21 | int h = 1080; 22 | 23 | //Choose P2D or P3D 24 | String renderer = P2D; 25 | 26 | @Override 27 | public void settings() { 28 | size(w, h, renderer); 29 | } 30 | 31 | @Override 32 | public void setup() { 33 | rectMode(CENTER); 34 | scene = onScreen ? new Scene(this, 1000) : new Scene(createGraphics(w, h, renderer), 1000); 35 | scene.eye().enableHint(Node.BOUNDS); 36 | //scene.fit(1000); 37 | scene.eye().setBullsEyeSize(50); 38 | scene.eye().setHighlight(0); 39 | //scene.eye().enableHint(Node.BULLSEYE); 40 | //scene.eye().enableHint(Node.FRUSTUM, scene, color(255, 0, 0, 125)); 41 | models = new Node[30]; 42 | for (int i = 0; i < models.length; i++) { 43 | if ((i & 1) == 0) { 44 | models[i] = new Node(shape()); 45 | } else { 46 | models[i] = new Node(); 47 | models[i].enableHint(Node.TORUS); 48 | models[i].scale(3); 49 | } 50 | scene.randomize(models[i]); 51 | } 52 | // Note that we pass the upper left corner coordinates where the minimap 53 | // is to be drawn (see drawing code below) to its constructor. 54 | minimap = new Scene(createGraphics(w / 2, h / 2, renderer), 2000); 55 | if (renderer == P3D) 56 | minimap.togglePerspective(); 57 | minimap.fit(1000); 58 | } 59 | 60 | PShape shape() { 61 | PShape shape = renderer == P3D ? createShape(BOX, 60) : createShape(RECT, 0, 0, 80, 100); 62 | shape.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 63 | return shape; 64 | } 65 | 66 | @Override 67 | public void keyPressed() { 68 | if (key == ' ') 69 | displayMinimap = !displayMinimap; 70 | if (key == 'i') { 71 | interactiveEye = !interactiveEye; 72 | if (interactiveEye) 73 | minimap.tag(scene.eye()); 74 | else 75 | minimap.untag(scene.eye()); 76 | } 77 | if (key == 'f') 78 | focus.fit(1000); 79 | if (key == 't') 80 | focus.togglePerspective(); 81 | } 82 | 83 | @Override 84 | public void mouseMoved() { 85 | if (!interactiveEye || focus == scene) 86 | focus.tag(); 87 | } 88 | 89 | @Override 90 | public void mouseDragged() { 91 | if (mouseButton == LEFT) 92 | focus.spin(); 93 | else if (mouseButton == RIGHT) 94 | focus.shift(); 95 | else 96 | focus.zoom(focus.mouseDX()); 97 | } 98 | 99 | @Override 100 | public void mouseWheel(MouseEvent event) { 101 | if (renderer == P3D) 102 | focus.moveForward(event.getCount() * 40); 103 | else 104 | focus.zoom(event.getCount() * 40); 105 | } 106 | 107 | @Override 108 | public void mouseClicked(MouseEvent event) { 109 | if (event.getCount() == 2) 110 | if (event.getButton() == LEFT) 111 | focus.focus(); 112 | else 113 | focus.align(); 114 | } 115 | 116 | @Override 117 | public void draw() { 118 | focus = minimap.hasFocus() ? minimap : scene; 119 | scene.openContext(); 120 | scene.context().background(75, 25, 15); 121 | scene.render(); 122 | scene.closeContext(); 123 | scene.image(); 124 | if (displayMinimap) { 125 | minimap.openContext(); 126 | minimap.context().background(125, 80, 90); 127 | minimap.render(); 128 | minimap.closeContext(); 129 | minimap.image(w / 2, h / 2); 130 | } 131 | } 132 | 133 | public static void main(String[] args) { 134 | PApplet.main(new String[]{"MiniMap"}); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /testing/src/Orbit.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Quaternion; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.core.PGraphics; 7 | import processing.core.PShape; 8 | import processing.event.MouseEvent; 9 | 10 | /** 11 | * Orbit around axis 12 | */ 13 | public class Orbit extends PApplet { 14 | Scene scene; 15 | Node shape1, shape2; 16 | Vector axis; 17 | 18 | public void settings() { 19 | size(800, 800, P3D); 20 | } 21 | 22 | public void setup() { 23 | rectMode(CENTER); 24 | scene = new Scene(this, 1000); 25 | scene.fit(1000); 26 | 27 | shape1 = new Node((PGraphics pGraphics) -> { 28 | Scene.drawAxes(pGraphics, scene.radius() / 3); 29 | pGraphics.pushStyle(); 30 | pGraphics.rectMode(CENTER); 31 | pGraphics.fill(255, 0, 255); 32 | if (scene.is3D()) 33 | Scene.drawCylinder(pGraphics, 30, scene.radius() / 4, 200); 34 | else 35 | pGraphics.rect(10, 10, 200, 200); 36 | pGraphics.popStyle(); 37 | }); 38 | shape1.setOrientation(Quaternion.random()); 39 | shape1.translate(-375, 175, -275); 40 | 41 | //shape2 = new Node(shape1); 42 | shape2 = new Node(); 43 | shape2.setShape(shape()); 44 | shape2.translate(275, 275, 275); 45 | 46 | scene.tag(shape2); 47 | axis = Vector.random(); 48 | axis.multiply(scene.radius() / 3); 49 | } 50 | 51 | public void draw() { 52 | background(0); 53 | stroke(0, 255, 0, 125); 54 | scene.drawArrow(axis); 55 | scene.drawAxes(); 56 | scene.render(); 57 | } 58 | 59 | public void keyPressed() { 60 | if (key == 'i') 61 | scene.tag(scene.hasTag(shape1) ? shape2 : shape1); 62 | if (key == 'f') 63 | Scene.leftHanded = !Scene.leftHanded; 64 | } 65 | 66 | public void mouseDragged() { 67 | if (mouseButton == LEFT) { 68 | if (shape2.isTagged(scene)) 69 | //shape2.rotate((mouseX-pmouseX)* PI / width, 0, 0, shape1); 70 | //shape2.rotateAround(new Quaternion(new Vector(0, 1, 0), (mouseX - pmouseX) * PI / width), shape1); 71 | //shape2.rotateAround(new Quaternion(new Vector(0, 1, 0), (mouseX - pmouseX) * PI / width), shape1); 72 | //shape2.orbit(new Quaternion(new Vector(0, 1, 0), (mouseX - pmouseX) * PI / width), shape1); 73 | shape2.orbit(axis, (mouseX - pmouseX) * PI / width); 74 | else 75 | scene.spin(); 76 | } else if (mouseButton == RIGHT) 77 | scene.spin(); 78 | //scene.translate(); 79 | //scene.mousePan(); 80 | } 81 | 82 | public void mouseWheel(MouseEvent event) { 83 | scene.zoom(event.getCount() * 20); 84 | } 85 | 86 | public void mouseClicked(MouseEvent event) { 87 | if (event.getCount() == 2) 88 | scene.focus(); 89 | } 90 | 91 | PShape shape() { 92 | PShape fig = scene.is3D() ? createShape(BOX, 150) : createShape(RECT, 0, 0, 150, 150); 93 | fig.setStroke(255); 94 | fig.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 95 | return fig; 96 | } 97 | 98 | public static void main(String[] args) { 99 | PApplet.main(new String[]{"Orbit"}); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /testing/src/OrthogonalViewer.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Vector; 3 | import nub.processing.Scene; 4 | import processing.core.PApplet; 5 | import processing.core.PGraphics; 6 | import processing.core.PShape; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * Setting up a viewer orthogonal to the current view helps 11 | * out to appreciate current objects depth within a scene 12 | */ 13 | public class OrthogonalViewer extends PApplet { 14 | Scene scene, visualHint, focus; 15 | int w = 500, h = 500, atX, atY; 16 | Node[] models; 17 | 18 | Vector orig = new Vector(); 19 | Vector dir = new Vector(); 20 | Vector end = new Vector(); 21 | Vector pup; 22 | 23 | @Override 24 | public void settings() { 25 | size(1800, 1400, P3D); 26 | } 27 | 28 | public void setup() { 29 | scene = new Scene(this, 1000); 30 | scene.fit(1000); 31 | models = new Node[100]; 32 | for (int i = 0; i < models.length; i++) { 33 | models[i] = new Node(boxShape()); 34 | scene.randomize(models[i]); 35 | } 36 | visualHint = new Scene(createGraphics(w, h, P3D), 300); 37 | } 38 | 39 | public void draw() { 40 | focus = pup != null ? visualHint.hasFocus() ? visualHint : scene : scene; 41 | background(0); 42 | drawRay(); 43 | scene.drawAxes(); 44 | scene.render(); 45 | if (pup != null) { 46 | visualHint.openContext(); 47 | visualHint.context().background(125); 48 | visualHint.render(); 49 | visualHint.closeContext(); 50 | visualHint.image(atX, atY); 51 | } 52 | } 53 | 54 | void drawRay() { 55 | PGraphics pg = scene.context(); 56 | if (pup != null) { 57 | pg.pushStyle(); 58 | pg.strokeWeight(20); 59 | pg.stroke(255, 255, 0); 60 | pg.point(pup.x(), pup.y(), pup.z()); 61 | pg.strokeWeight(8); 62 | pg.stroke(0, 0, 255); 63 | pg.line(orig.x(), orig.y(), orig.z(), end.x(), end.y(), end.z()); 64 | pg.popStyle(); 65 | } 66 | } 67 | 68 | public void mouseClicked(MouseEvent event) { 69 | if (event.getCount() == 1) 70 | scene.focus(); 71 | else 72 | scene.align(); 73 | } 74 | 75 | PShape boxShape() { 76 | PShape box = createShape(BOX, 60); 77 | box.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 78 | return box; 79 | } 80 | 81 | @Override 82 | public void mouseMoved(MouseEvent event) { 83 | if (event.isControlDown()) { 84 | pup = scene.location(); 85 | if (pup != null) { 86 | visualHint.setCenter(pup); 87 | visualHint.setRadius(300); 88 | visualHint.eye().setWorldPosition(pup); 89 | //hint.setViewDirection(scene.displacement(Vector.plusJ)); 90 | visualHint.setViewDirection(scene.displacement(new Vector(0, 1, 0))); 91 | visualHint.setUpVector(scene.displacement(new Vector(0, 0, -1))); 92 | visualHint.fit(); 93 | atX = mouseX - w / 2; 94 | atY = mouseY - h; 95 | // debug 96 | scene.pixelToLine(orig, dir); 97 | end = Vector.add(orig, Vector.multiply(dir, 4000.0f)); 98 | } 99 | } else { 100 | focus.tag(); 101 | } 102 | } 103 | 104 | @Override 105 | public void mouseDragged() { 106 | if (mouseButton == LEFT) 107 | focus.spin(); 108 | else if (mouseButton == RIGHT) 109 | focus.shift(); 110 | else 111 | focus.moveForward(focus.mouseDX()); 112 | } 113 | 114 | @Override 115 | public void mouseWheel(MouseEvent event) { 116 | focus.zoom(event.getCount() * 20); 117 | } 118 | 119 | @Override 120 | public void keyPressed() { 121 | if (key == ' ') 122 | scene.togglePerspective(); 123 | if (key == 'f') 124 | Scene.leftHanded = !Scene.leftHanded; 125 | } 126 | 127 | public static void main(String[] args) { 128 | PApplet.main(new String[]{"OrthogonalViewer"}); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /testing/src/PointUnderPixel.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.primitives.Vector; 3 | import nub.processing.Scene; 4 | import processing.core.PApplet; 5 | import processing.core.PConstants; 6 | import processing.core.PShape; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * Pick a point under pixel using the scene location method 11 | */ 12 | public class PointUnderPixel extends PApplet { 13 | Scene scene; 14 | Node[] models; 15 | 16 | Vector orig = new Vector(); 17 | Vector dir = new Vector(); 18 | Vector end = new Vector(); 19 | Vector pup; 20 | 21 | // offScreen breaks reading depths in Processing 22 | // try offScreen = false to see how it should work 23 | boolean offScreen = false; 24 | 25 | @Override 26 | public void settings() { 27 | size(800, 800, P3D); 28 | //noSmooth(); 29 | } 30 | 31 | public void setup() { 32 | scene = offScreen ? new Scene(createGraphics(width, height, P3D), 1000) : new Scene(this, 1000); 33 | scene.fit(1000); 34 | models = new Node[100]; 35 | for (int i = 0; i < models.length; i++) { 36 | models[i] = new Node(boxShape()); 37 | scene.randomize(models[i]); 38 | } 39 | if (offScreen) { 40 | scene.context().hint(PConstants.ENABLE_BUFFER_READING); 41 | } 42 | } 43 | 44 | public void draw() { 45 | background(0); 46 | scene.render(); 47 | scene.drawAxes(); 48 | stroke(0,255,0); 49 | scene.drawGrid(); 50 | drawRay(); 51 | } 52 | 53 | void drawRay() { 54 | if (pup != null) { 55 | pushStyle(); 56 | strokeWeight(20); 57 | stroke(255, 255, 0); 58 | point(pup.x(), pup.y(), pup.z()); 59 | strokeWeight(8); 60 | stroke(0, 0, 255); 61 | line(orig.x(), orig.y(), orig.z(), end.x(), end.y(), end.z()); 62 | popStyle(); 63 | } 64 | } 65 | 66 | public void mouseClicked(MouseEvent event) { 67 | if (event.getButton() == RIGHT) { 68 | pup = scene.location(); 69 | if (pup != null) { 70 | scene.pixelToLine(orig, dir); 71 | end = Vector.add(orig, Vector.multiply(dir, 4000.0f)); 72 | } 73 | } else { 74 | if (event.getCount() == 1) 75 | scene.focus(); 76 | else 77 | scene.align(); 78 | } 79 | } 80 | 81 | PShape boxShape() { 82 | PShape box = createShape(BOX, 60); 83 | box.setFill(color(random(0, 255), random(0, 255), random(0, 255))); 84 | return box; 85 | } 86 | 87 | @Override 88 | public void mouseMoved() { 89 | scene.tag(); 90 | } 91 | 92 | @Override 93 | public void mouseDragged() { 94 | if (mouseButton == LEFT) 95 | scene.spin(); 96 | else if (mouseButton == RIGHT) 97 | scene.shift(); 98 | else 99 | scene.moveForward(scene.mouseDX()); 100 | } 101 | 102 | @Override 103 | public void mouseWheel(MouseEvent event) { 104 | scene.zoom(event.getCount() * 20); 105 | } 106 | 107 | @Override 108 | public void keyPressed() { 109 | if (key == ' ') 110 | scene.togglePerspective(); 111 | if (key == 'f') 112 | Scene.leftHanded = !Scene.leftHanded; 113 | } 114 | 115 | public static void main(String[] args) { 116 | PApplet.main(new String[]{"PointUnderPixel"}); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /testing/src/SceneBuffers.java: -------------------------------------------------------------------------------- 1 | import nub.core.Node; 2 | import nub.processing.Scene; 3 | import processing.core.PApplet; 4 | import processing.core.PGraphics; 5 | import processing.core.PShape; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Picking buffer debugging 10 | */ 11 | public class SceneBuffers extends PApplet { 12 | Scene scene; 13 | Node root, cajas, bolas; 14 | Node[] shapes; 15 | 16 | //Choose one of P3D for a 3D scene or P2D for a 2D one. 17 | String renderer = P3D; 18 | int w = 1200; 19 | int h = 1200; 20 | 21 | public void settings() { 22 | size(w, h, renderer); 23 | } 24 | 25 | public void setup() { 26 | rectMode(CENTER); 27 | scene = new Scene(createGraphics(w, h / 2, renderer), max(w, h)); 28 | //scene = new Scene(createGraphics(w, h, renderer), max(w, h)); 29 | //scene = new Scene(this, 1200); 30 | cajas = new Node(); 31 | bolas = new Node(); 32 | scene.randomize(cajas); 33 | scene.randomize(bolas); 34 | shapes = new Node[10]; 35 | for (int i = 0; i < shapes.length; i++) { 36 | if (i%2==0) { 37 | shapes[i] = new Node(cajas, caja()); 38 | } 39 | else { 40 | shapes[i] = new Node(bolas, bola()); 41 | } 42 | scene.randomize(shapes[i]); 43 | //shapes[i].enableHint(Node.CAMERA); 44 | shapes[i].enableHint(Node.AXES); 45 | shapes[i].setHUD(this::hud); 46 | } 47 | scene.fit(1000); 48 | } 49 | 50 | public void hud(PGraphics pg) { 51 | pg.pushStyle(); 52 | pg.rectMode(CENTER); 53 | pg.fill(255, 0, 255, 125); 54 | pg.stroke(0,0,255); 55 | pg.strokeWeight(3); 56 | pg.rect(0, 0, 80, 50); 57 | pg.popStyle(); 58 | } 59 | 60 | public void draw() { 61 | // 1. Fill in and display front-buffer 62 | /* 63 | background(0); 64 | scene.render(bolas); 65 | scene.render(cajas); 66 | // */ 67 | // /* 68 | scene.display(color(125), bolas); 69 | scene.display(cajas); 70 | // */ 71 | /* 72 | scene.openContext(); 73 | scene.context().background(125); 74 | scene.drawAxes(); 75 | scene.render(cajas); 76 | //scene.render(bolas); 77 | scene.closeContext(); 78 | //scene.image(); 79 | // */ 80 | 81 | /* 82 | scene.openContext(); 83 | //scene.context().background(125); 84 | //scene.drawAxes(); 85 | //scene.render(cajas); 86 | scene.render(bolas); 87 | scene.closeContext(); 88 | scene.image(); 89 | // */ 90 | 91 | //scene.display(125, root); 92 | // 2. Display back buffer 93 | scene.displayBackBuffer(color(255, 0, 0),0, h / 2); 94 | } 95 | 96 | public void mouseMoved() { 97 | scene.tag(); 98 | } 99 | 100 | public void mouseDragged() { 101 | if (mouseButton == LEFT) 102 | scene.spin(); 103 | else if (mouseButton == RIGHT) 104 | scene.shift(); 105 | else 106 | scene.zoom(mouseX - pmouseX); 107 | } 108 | 109 | public void mouseWheel(MouseEvent event) { 110 | if (scene.is3D()) 111 | scene.moveForward(event.getCount() * 20); 112 | else 113 | scene.zoom(event.getCount() * 20); 114 | } 115 | 116 | public void keyPressed() { 117 | if (key == '0') 118 | root = null; 119 | if (key == '1') 120 | root = cajas; 121 | if (key == '2') 122 | root = bolas; 123 | } 124 | 125 | PShape caja() { 126 | PShape caja = scene.is3D() ? createShape(BOX, random(60, 100)) : createShape(RECT, 0, 0, random(60, 100), random(60, 100)); 127 | caja.setStrokeWeight(3); 128 | caja.setStroke(color(random(0, 255), random(0, 255), random(0, 255))); 129 | caja.setFill(color(random(0, 255), random(0, 255), random(0, 255), random(0, 255))); 130 | return caja; 131 | } 132 | 133 | PShape bola() { 134 | PShape bola = scene.is3D() ? createShape(SPHERE, random(60, 100)) : createShape(ELLIPSE, 0, 0, random(60, 100), random(60, 100)); 135 | //bola.noStroke(); 136 | bola.setStroke(color(random(0, 255), random(0, 255), random(0, 255))); 137 | bola.setFill(color(random(0, 255), random(0, 255), random(0, 255), random(0, 255))); 138 | return bola; 139 | } 140 | 141 | public static void main(String args[]) { 142 | PApplet.main(new String[]{"SceneBuffers"}); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /testing/src/Superliminal.java: -------------------------------------------------------------------------------- 1 | import nub.core.Graph; 2 | import nub.core.Node; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.event.MouseEvent; 7 | 8 | /** 9 | * Superliminal (https://t.ly/_brt) gameplay 10 | * implemented from graph sceneToPixelRatio method 11 | */ 12 | public class Superliminal extends PApplet { 13 | Scene scene, lateralView, focus; 14 | Node[] cubes; 15 | boolean displayLateralView; 16 | // whilst scene1 is either on-screen or not; scene2 and scene3 are off-screen 17 | // test both cases here 18 | boolean onScreen = false; 19 | 20 | int w = 1920; 21 | int h = 1080; 22 | 23 | public void settings() { 24 | size(w, h, P3D); 25 | } 26 | 27 | public void setup() { 28 | scene = onScreen ? new Scene(g) : new Scene(createGraphics(w, h, P3D)); 29 | scene.eye().enableHint(Node.BOUNDS); 30 | scene.eye().tagging = false; 31 | scene.setRadius(200); 32 | scene.fit(1000); 33 | cubes = new Node[15]; 34 | for (int i = 0; i < cubes.length; i++) { 35 | cubes[i] = new CustomNode(); 36 | //shapes[i].setHUD(this::hud); 37 | //shapes[i].disablePicking(Node.SHAPE); 38 | //shapes[i].enableHint(Node.BULLSEYE); 39 | //shapes[i].disablePickingMode(Node.SHAPE); 40 | scene.randomize(cubes[i]); 41 | } 42 | 43 | // Note that we pass the upper left corner coordinates where the scene1 44 | // is to be drawn (see drawing code below) to its constructor. 45 | lateralView = new Scene(createGraphics(w / 2, h, P3D)); 46 | lateralView.togglePerspective(); 47 | lateralView.eye().tagging = false; 48 | lateralView.setRadius(400); 49 | lateralView.fit(); 50 | 51 | /* 52 | int si = int(vertTexCoord.s * binsize); 53 | vec2(float(si) / binsize 54 | // */ 55 | 56 | /* 57 | float w = 600; 58 | float binsize = 5; 59 | float vertTexCoord; 60 | float coef = w / binsize; 61 | for(float i = 0; i < w; i++) { 62 | vertTexCoord = i / w; 63 | int si = (int) (vertTexCoord * coef); 64 | println(vertTexCoord + " " + ((float)(si)) / coef); 65 | } 66 | // */ 67 | 68 | /* 69 | float binsize = 5; 70 | //float vertTexCoord; 71 | for(float i = 0; i < 1; i+=1/600f) { 72 | //vertTexCoord = i; 73 | int si = (int) (i * binsize); 74 | println(i + " " + ((float)(si)) / binsize); 75 | } 76 | // */ 77 | 78 | /* 79 | float w = 600; 80 | float binsize = 5; 81 | //float vertTexCoord; 82 | float coef = w / binsize; 83 | for(float i = 0; i < w; i++) { 84 | //vertTexCoord = i / w; 85 | int si = (int) (i * coef); 86 | println(i + " " + ((float)(si)) / coef); 87 | } 88 | // */ 89 | 90 | /* 91 | float w = 600; 92 | float binsize = 5; 93 | float vertTexCoord; 94 | float coef = w / binsize; 95 | for(float i = 0; i < w; i++) { 96 | vertTexCoord = i / w; 97 | int si = (int) (vertTexCoord * binsize); 98 | println(i + " " + vertTexCoord + " " + ((float)(si)) / binsize); 99 | } 100 | // */ 101 | } 102 | 103 | class CustomNode extends Node { 104 | //Add some attributes 105 | float radiusInPixels = 50, radius; 106 | int strokeCol = color(255, 255, 0), fillCol = color(0, 255, 255, 125); 107 | 108 | public CustomNode() { 109 | super(); 110 | setShape(pg -> { 111 | //this.radius = this.radiusInPixels; 112 | this.radius = this.radiusInPixels * scene.sceneToPixelRatio(worldPosition()); 113 | pg.pushStyle(); 114 | pg.stroke(strokeCol); 115 | pg.fill(fillCol); 116 | pg.box(radius); 117 | pg.popStyle(); 118 | }); 119 | } 120 | } 121 | 122 | public void keyPressed() { 123 | if (key == ' ') 124 | displayLateralView = !displayLateralView; 125 | if (key == 'f') 126 | focus.fit(1000); 127 | if (key == 't') { 128 | if (focus == null) 129 | return; 130 | focus.togglePerspective(); 131 | } 132 | } 133 | 134 | @Override 135 | public void mouseMoved() { 136 | if (focus == null) 137 | return; 138 | focus.tag(); 139 | } 140 | 141 | @Override 142 | public void mouseDragged() { 143 | if (focus == null) 144 | return; 145 | if (mouseButton == LEFT) 146 | focus.spin(); 147 | else if (mouseButton == RIGHT) 148 | focus.shift(); 149 | else { 150 | focus.zoom(mouseX - pmouseX); 151 | } 152 | } 153 | 154 | @Override 155 | public void mouseWheel(MouseEvent event) { 156 | Node node = scene.node(); 157 | Node eye = scene.eye(); 158 | if(node != null) { 159 | float amount = event.getCount(); 160 | //scene.translateNode(node, 0, 0, amount / 50, Scene.inertia); 161 | ///* 162 | if (scene.type() == Graph.Type.PERSPECTIVE) { 163 | Vector v = Vector.subtract(node.worldPosition(), eye.worldPosition()); 164 | v.normalize(); 165 | v.multiply(amount * 10); 166 | node.translate(v, Scene.inertia); 167 | } 168 | else { 169 | scene.shift(node, 0, 0, amount / 50, Scene.inertia); 170 | } 171 | // */ 172 | } 173 | else { 174 | focus.moveForward(event.getCount() * 20); 175 | } 176 | } 177 | 178 | @Override 179 | public void mouseClicked(MouseEvent event) { 180 | if (focus == null) 181 | return; 182 | if (event.getCount() == 2) 183 | if (event.getButton() == LEFT) 184 | focus.focus(); 185 | else 186 | focus.align(); 187 | } 188 | 189 | public void draw() { 190 | focus = lateralView.hasFocus() ? lateralView : scene; 191 | scene.openContext(); 192 | scene.context().background(75, 25, 15); 193 | scene.render(); 194 | scene.closeContext(); 195 | scene.image(); 196 | //stroke(0, 225, 15); 197 | //scene.drawGrid(); 198 | if (displayLateralView) { 199 | lateralView.openContext(); 200 | lateralView.context().background(75, 25, 175); 201 | lateralView.drawAxes(); 202 | lateralView.render(); 203 | lateralView.closeContext(); 204 | lateralView.image(w / 2, 0); 205 | } 206 | } 207 | 208 | public static void main(String[] args) { 209 | PApplet.main(new String[]{"Superliminal"}); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /testing/src/ViewFrustumCulling.java: -------------------------------------------------------------------------------- 1 | import nub.core.Graph; 2 | import nub.core.Node; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.core.PGraphics; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * View frustum culling (https://t.ly/fap6a) 11 | * implemented with node visibility routines and custom behavior 12 | */ 13 | public class ViewFrustumCulling extends PApplet { 14 | OctreeNode root; 15 | Scene mainScene, secondaryScene, focus; 16 | 17 | int w = 700; 18 | int h = 700; 19 | //octree 20 | float a = 220, b = 100, c = 280; 21 | int levels = 4; 22 | 23 | public void settings() { 24 | size(w, h, P3D); 25 | } 26 | 27 | public void setup() { 28 | // main scene 29 | mainScene = new Scene(createGraphics(w, h / 2, P3D)); 30 | mainScene.eye().enableHint(Node.BOUNDS); 31 | mainScene.togglePerspective(); 32 | mainScene.fit(1000); 33 | // secondary scene 34 | secondaryScene = new Scene(createGraphics(w, h / 2, P3D), 200); 35 | secondaryScene.togglePerspective(); 36 | secondaryScene.fit(); 37 | // declare and build the octree hierarchy 38 | root = new OctreeNode(); 39 | buildOctree(root); 40 | } 41 | 42 | public void buildOctree(OctreeNode parent) { 43 | if (parent.level() < levels) 44 | for (int i = 0; i < 8; ++i) 45 | buildOctree(new OctreeNode(parent, new Vector((i & 4) == 0 ? a : -a, (i & 2) == 0 ? b : -b, (i & 1) == 0 ? c : -c))); 46 | } 47 | 48 | public void draw() { 49 | focus = mainScene.hasFocus() ? mainScene : secondaryScene; 50 | // culling condition should be retested every frame 51 | root.cull = false; 52 | mainScene.openContext(); 53 | mainScene.context().background(255); 54 | mainScene.render(); 55 | mainScene.closeContext(); 56 | mainScene.image(); 57 | secondaryScene.openContext(); 58 | secondaryScene.context().background(185); 59 | secondaryScene.render(); 60 | secondaryScene.closeContext(); 61 | secondaryScene.image(0, h / 2); 62 | } 63 | 64 | void handleMouse() { 65 | focus = mouseY < h / 2 ? mainScene : secondaryScene; 66 | } 67 | 68 | public void mouseDragged() { 69 | if (mouseButton == LEFT) 70 | focus.spin(); 71 | else if (mouseButton == RIGHT) 72 | focus.shift(); 73 | else 74 | focus.zoom(mouseX - pmouseX); 75 | } 76 | 77 | public void mouseWheel(MouseEvent event) { 78 | focus.moveForward(event.getCount() * 20); 79 | } 80 | 81 | public void mouseClicked(MouseEvent event) { 82 | if (event.getCount() == 2) 83 | if (event.getButton() == LEFT) 84 | focus.focus(); 85 | else 86 | focus.align(); 87 | } 88 | 89 | public void keyPressed() { 90 | if (key == ' ') 91 | focus.togglePerspective(); 92 | if (key == 'f') { 93 | Scene.leftHanded = !Scene.leftHanded; 94 | } 95 | if (key == 's') { 96 | focus.fit(1000); 97 | } 98 | } 99 | 100 | class OctreeNode extends Node { 101 | OctreeNode() { 102 | tagging = false; 103 | setShape(this::draw); 104 | setBehavior(mainScene, this::culling); 105 | } 106 | 107 | OctreeNode(OctreeNode node, Vector vector) { 108 | super(node); 109 | scale(0.5f); 110 | translate(Vector.multiply(vector, magnitude() / 2)); 111 | tagging = false; 112 | setShape(this::draw); 113 | setBehavior(mainScene, this::culling); 114 | } 115 | 116 | float level() { 117 | return 1 - log(worldMagnitude()) / log(2); 118 | } 119 | 120 | public void draw(PGraphics pg) { 121 | float level = level(); 122 | pg.stroke(color(0.3f * level * 255, 0.2f * 255, (1 - 0.3f * level) * 255)); 123 | pg.strokeWeight(pow(2, levels - 1)); 124 | pg.noFill(); 125 | pg.box(a, b, c); 126 | } 127 | 128 | // The culling method is called just before the graphics(PGraphics) method 129 | public void culling(Graph graph, Node node) { 130 | switch (graph.boxVisibility(node.worldLocation(new Vector(-a / 2, -b / 2, -c / 2)), 131 | node.worldLocation(new Vector(a / 2, b / 2, c / 2)))) { 132 | case VISIBLE: 133 | for (Node child : node.children()) 134 | child.cull = true; 135 | break; 136 | case SEMIVISIBLE: 137 | if (!node.children().isEmpty()) { 138 | // don't render the node... 139 | node.bypass(); 140 | // ... but don't cull its children either 141 | for (Node child : node.children()) 142 | child.cull = false; 143 | } 144 | break; 145 | case INVISIBLE: 146 | node.cull = true; 147 | break; 148 | } 149 | } 150 | } 151 | 152 | public static void main(String args[]) { 153 | PApplet.main(new String[]{"ViewFrustumCulling"}); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /testing/src/VisitExample.java: -------------------------------------------------------------------------------- 1 | import nub.core.Graph; 2 | import nub.core.Node; 3 | import nub.primitives.Vector; 4 | import nub.processing.Scene; 5 | import processing.core.PApplet; 6 | import processing.core.PGraphics; 7 | import processing.event.MouseEvent; 8 | 9 | /** 10 | * This example modifies the visual representation on a Node 11 | * depending on the scene it is drawn. It demos custom scene behavior 12 | * 13 | * By Sebastian Chaparro 14 | */ 15 | public class VisitExample extends PApplet { 16 | boolean relativeToGraph = true; 17 | int rows = 2, cols = 2; 18 | int n = rows * cols; 19 | Scene[] scenes = new Scene[n]; 20 | Scene focus; 21 | int w = 1400, h = 1400; 22 | int[] strokeColors = new int[n]; 23 | int[] fillColors = new int[n]; 24 | 25 | public void settings() { 26 | size(w, h, P3D); 27 | } 28 | 29 | @Override 30 | public void setup() { 31 | //create the scenes 32 | for(int i = 0; i < n; i++){ 33 | final int idx = i; 34 | scenes[i] = new Scene(createGraphics(w / cols, h / rows, P3D)); 35 | scenes[i].setRadius(50); 36 | strokeColors[i] = color(random(255), random(255), random(255)); 37 | fillColors[i] = color(random(255), random(255), random(255)); 38 | scenes[i].fit(); 39 | if(Math.random() < 0.5) scenes[i].togglePerspective(); 40 | 41 | } 42 | generateRandomNodes(10); 43 | } 44 | 45 | @Override 46 | public void draw() { 47 | for(int i = 0; i < n; i++){ 48 | focus = scenes[i].hasFocus() ? scenes[i] : focus; 49 | scenes[i].openContext(); 50 | scenes[i].context().background(125); 51 | scenes[i].render(); 52 | scenes[i].drawAxes(); 53 | scenes[i].beginHUD(); 54 | sceneHUD(i, scenes[i].context()); 55 | scenes[i].endHUD(); 56 | scenes[i].closeContext(); 57 | scenes[i].image(i / rows * h / rows, (i % cols) * w / cols); 58 | } 59 | } 60 | 61 | public void sceneHUD(int i, PGraphics pg) { 62 | pg.pushStyle(); 63 | pg.stroke(255); 64 | pg.fill(255); 65 | pg.text("On scene " + i + " radius : " + (int) (scenes[i].radius()), 10, pg.height / 10); 66 | pg.popStyle(); 67 | } 68 | 69 | public void generateRandomNodes(int n) { 70 | for(int i = 0; i < n; i++){ 71 | Node node = new CustomNode(); 72 | node.randomize(new Vector(), 150, true); 73 | node.setMagnitude(1); 74 | } 75 | } 76 | 77 | class CustomNode extends Node { 78 | //Add some attributes 79 | float radiusInPixels = 50, radius; 80 | int strokeCol, fillCol; 81 | 82 | public CustomNode() { 83 | super(); 84 | //without modifying Node class 85 | //for(Scene scene : scenes) setVisit(scene, (g , n) -> setupAttributesByGraph(g)); 86 | //modifying the node class 87 | for (Scene scene : scenes) setBehavior(scene, this::setupAttributesByGraph); 88 | setShape(pg -> { 89 | pg.pushStyle(); 90 | pg.stroke(strokeCol); 91 | pg.fill(fillCol); 92 | pg.box(radius); 93 | pg.popStyle(); 94 | }); 95 | } 96 | 97 | public void setupAttributesByGraph(Graph g) { 98 | if (relativeToGraph) { 99 | //keep the size of the node relative to the graph such that it always occupies 10 pixels 100 | this.radius = this.radiusInPixels * g.sceneToPixelRatio(worldPosition()); 101 | //change color based on Graph 102 | for (int i = 0; i < n; i++) { 103 | if (g == scenes[i]) { 104 | this.strokeCol = strokeColors[i]; 105 | this.fillCol = fillColors[i]; 106 | } 107 | } 108 | } else{ 109 | this.radius = 10; 110 | this.strokeCol = color(255); 111 | this.fillCol = color(255,255, 0); 112 | } 113 | } 114 | } 115 | 116 | @Override 117 | public void mouseMoved(){ 118 | focus.tag(); 119 | } 120 | 121 | @Override 122 | public void mouseDragged() { 123 | if(mouseButton == LEFT) 124 | focus.spin(); 125 | else if(mouseButton == RIGHT) 126 | focus.shift(); 127 | else 128 | focus.zoom(focus.mouseDX()); 129 | } 130 | 131 | @Override 132 | public void mouseWheel(MouseEvent event) { 133 | focus.moveForward(event.getCount() * 40); 134 | } 135 | 136 | @Override 137 | public void mouseClicked(MouseEvent event) { 138 | if (event.getCount() == 2) 139 | if (event.getButton() == LEFT) 140 | focus.focus(); 141 | else 142 | focus.align(); 143 | } 144 | 145 | @Override 146 | public void keyPressed() { 147 | if (key == ' ') { 148 | relativeToGraph = !relativeToGraph; 149 | } 150 | } 151 | 152 | public static void main(String[] args) { 153 | PApplet.main(new String[]{"VisitExample"}); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /testing/testing.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | ##library.name## 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 25 | 26 | 38 | 39 |
40 | 41 |
42 |

##library.name##

43 |

44 | A library by ##author.name## for the Processing programming environment.
45 | Last update, ##date##. 46 |

47 |

48 | ##library.sentence##
49 | ##library.paragraph##
50 | Feel free to replace this paragraph with a description of the library.
51 | Contributed libraries are developed, documented, and maintained by members of the Processing community. Further directions are included with each library. For feedback and support, please post to the Discourse. We strongly encourage all libraries to be open source, but not all of them are. 52 |

53 |
54 | 55 | 56 | 57 |
58 |

Download

59 |

60 | Download ##library.name## version ##library.prettyVersion## (##library.version##) in 61 | .zip format. 62 |

63 |

Installation

64 |

65 | Unzip and put the extracted ##project.name## folder into the libraries folder of your Processing sketches. Reference and examples are included in the ##project.name## folder. 66 |

67 |
68 | 69 | 70 |
71 |

Keywords. ##library.keywords##

72 |

Reference. Have a look at the javadoc reference here. A copy of the reference is included in the .zip as well.

73 |

Source. The source code of ##library.name## is available at ##source.host##, and its repository can be browsed here.

74 |
75 | 76 | 77 |
78 |

Examples

79 |

Find a list of examples in the current distribution of ##library.name##, or have a look at them by following the links below.

80 |
    81 | ##examples## 82 |
83 |
84 | 85 | 86 |
87 |

Tested

88 |

89 | 90 | Platform ##tested.platform## 91 | 92 | 93 |
Processing ##tested.processingVersion## 94 | 95 | 96 |
Dependencies ##library.dependencies## 97 |

98 |
99 | 100 | 101 | 102 | 114 | 115 | 116 | 121 | 122 | 123 | 127 | 128 | 129 |
130 |
131 | 132 | 135 |
136 | 137 | -------------------------------------------------------------------------------- /web/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* processingLibs style by andreas schlegel, sojamo. */ 2 | 3 | 4 | * { 5 | margin:0; 6 | padding:0; 7 | border:0; 8 | } 9 | 10 | 11 | body { 12 | font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; 13 | font-size : 100%; 14 | font-size : 0.70em; 15 | font-weight : normal; 16 | line-height : normal; 17 | } 18 | 19 | 20 | 21 | #container { 22 | margin-left:64px; 23 | background-color:#fff; 24 | } 25 | 26 | #header { 27 | float:left; 28 | padding-top:24px; 29 | padding-bottom:48px; 30 | } 31 | 32 | #menu { 33 | margin-top:16px; 34 | float:left; 35 | margin-bottom:64px; 36 | } 37 | 38 | 39 | #about, 40 | #download, 41 | #examples, 42 | #demos, 43 | #misc { 44 | width:480px; 45 | float:left; 46 | margin-right:24px; 47 | } 48 | 49 | 50 | #resources, #info { 51 | width:320px; 52 | float:left; 53 | } 54 | 55 | 56 | .clear { 57 | clear:both; 58 | } 59 | 60 | #footer { 61 | margin-top:300px; 62 | height:20px; 63 | margin-bottom:32px; 64 | } 65 | 66 | 67 | ul { 68 | list-style:none; 69 | padding:0; 70 | margin:0; 71 | } 72 | 73 | 74 | #menu ul li, #subMenu ul li { 75 | float:left; 76 | padding-right:6px; 77 | } 78 | 79 | 80 | 81 | 82 | 83 | 84 | /* Headings */ 85 | 86 | h1 { 87 | font-size:2em; 88 | font-weight:normal; 89 | } 90 | 91 | 92 | h2, h3, h4, h5, th { 93 | font-size:1.3em; 94 | font-weight:normal; 95 | margin-bottom:4px; 96 | } 97 | 98 | 99 | 100 | p { 101 | font-size:1em; 102 | width:90%; 103 | margin-bottom:32px; 104 | } 105 | 106 | 107 | pre, code { 108 | font-family:"Courier New", Courier, monospace; 109 | font-size:1em; 110 | line-height:normal; 111 | } 112 | 113 | 114 | 115 | 116 | hr { 117 | border:0; 118 | height:1px; 119 | margin-bottom:24px; 120 | } 121 | 122 | 123 | a { 124 | text-decoration: underline; 125 | font-weight: normal; 126 | } 127 | 128 | 129 | a:hover, 130 | a:active { 131 | text-decoration: underline; 132 | font-weight: normal; 133 | } 134 | 135 | 136 | a:visited, 137 | a:link:visited { 138 | text-decoration: underline; 139 | font-weight: normal; 140 | } 141 | 142 | 143 | 144 | img { 145 | border: 0px solid #000000; 146 | } 147 | 148 | 149 | 150 | 151 | 152 | /* COLORS */ 153 | 154 | 155 | body { 156 | color : #333; 157 | background-color :#fff; 158 | } 159 | 160 | 161 | #header { 162 | background-color:#fff; 163 | color:#333; 164 | } 165 | 166 | 167 | 168 | h1, h2, h3, h4, h5, h6 { 169 | color:#666; 170 | } 171 | 172 | 173 | pre, code { 174 | color: #000000; 175 | } 176 | 177 | 178 | a,strong { 179 | color: #333; 180 | } 181 | 182 | 183 | a:hover, 184 | a:active { 185 | color: #333; 186 | } 187 | 188 | 189 | a:visited, 190 | a:link:visited { 191 | color: #333; 192 | } 193 | 194 | 195 | #footer, #menu { 196 | background-color:#fff; 197 | color:#333; 198 | } 199 | 200 | 201 | #footer a, #menu a { 202 | color:#333; 203 | } 204 | --------------------------------------------------------------------------------