sechaparroc / proscenejs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FramesJS All Contributors

Table of Contents

Description

Frames is a simple, expressive, language-agnostic, and extensible (2D/3D) scene graph featuring interaction, visualization and animation frameworks and supporting advanced (onscreen/offscreen) rendering techniques, such as view frustum culling.

Frames is meant to be coupled with third party real and non-real time renderers. Our current release supports all major Processing desktop renderers: 2D and 3D PGraphicsOpenGL (a.k.a. P2D and P3D, respectively), PGraphicsJava2D (a.k.a. JAVA2D) and PGraphicsFX2D (a.k.a. FX2D).

If looking for the API docs, check them here.

Readers unfamiliar with geometry transformations may first check the great Processing 2D transformations tutorial by J David Eisenberg and this presentation that discusses some related formal foundations.

Scene

Instantiate your on-screen scene at the setup():

Scene scene;
void setup() {
  scene = new Scene(this);
}

The Scene frontBuffer() corresponds to the PApplet main PGraphics instance.

Off-screen scenes should be instantiated upon a PGraphics object:

Scene scene;
void setup() {
  scene = new Scene(this, createGraphics(500, 500, P3D));
}

In this case, the Scene frontBuffer() corresponds to the PGraphics instantiated with createGraphics() (which is of course different than the PApplet main PGraphics instance).

Frames

A frame is a coordinate system that may be translated, rotated and scaled. Frame instances define each of the nodes comprising a scene graph. To customize their role (e.g., a drawing procedure or a culling condition) symply override the Frame visit() method. To illustrate their use, suppose the following scene graph is being implemented:

 World
  ^
  |\
  1 eye
  ^
  |\
  2 3

To setup the scene hierarchy of attached frames, i.e., frames belonging to the scene, use code such as the following:

Scene scene;
Frame f1, f2, f3;
void setup() {
  scene = new Scene(this);
  // To attach a leading-frame (those whose parent is the world, such as f1)
  // the scene parameter is passed to the Frame constructor:
  f1 = new Frame(scene);
  // whereas for the remaining frames we pass any constructor taking a
  // reference frame paramater, such as Frame(Frame referenceFrame)
  f2 = new Frame(f1);
  f3 = new Frame(f1) {
    // note that within visit() the geometry is defined
    // at the frame local coordinate system
    @Override
    public void visit() {
      sphere(50);
    }
  };
}

and then traverse it with:

void draw() {
  // traverse() peforms a top-down traversal of the frame hierarchy, applying the
  // local frame transformation and calling the visit() method on each visited frame
  scene.traverse();
}

To set the scene tracked-frame (the frame the mouse should interact with) call setTrackedFrame(Frame) or update it using ray-casting with cast(), for example:

void mouseMoved() {
  // the tracked-frame is updated using ray-casting from the set of scene attached frames
  scene.cast();
}

To interact with a given frame use any Scene method that takes a Frame parameter, such as: spin(Frame), translate(Frame), scale(float, Frame) or zoom(float, Frame). For example:

public void mouseDragged() {
  // spin f1
  if (mouseButton == LEFT)
    scene.spin(f1);
  // translate f3
  else if (mouseButton == RIGHT)
    scene.translate(f3);
  // zoom f2
  else
    scene.zoom(scene.mouseDX(), f2);
}

To interact with the default-frame (which is either the tracked-frame updated with the mouseMoved above or the scene eye when the tracked-frame is null) use the frameless versions of the above methods, e.g., spin(), translate(), scale(float) or zoom(float). For example:

public void mouseDragged() {
  // spins the default-frame (the eye or the frame picked with a mouseMoved)
  if (mouseButton == LEFT)
    scene.spin();
  else if (mouseButton == RIGHT)
  // translates the default-frame (the eye or the frame picked with a mouseMoved)
    scene.translate();
  // zooms the default-frame (the eye or the frame picked with a mouseMoved)
  else
    scene.zoom(scene.mouseDX());
}

See the CajasOrientadas example. Some advantages of using attached frames are:

To bypass the traverse() algorithm use detached frames, or override visit() to setup a cullingCondition for the frame as follows (see visit(), cull(boolean) and isCulled()):

Scene scene;
Frame frame;
void setup() {
  scene = new Scene(this);
  frame = new Frame(scene) {
    @Override
    public void visit() {
      // Hierarchical culling is optional and disabled by default. When the cullingCondition
      // (which should be implemented by you) is true, scene.traverse() will prune the branch at the frame
      cull(cullingCondition);
      if(!isCulled())
        // Draw your object here, in the local coordinate system.
    }
  }
}

Shapes

A Shape is an attached Frame specialization that can be set from a retained-mode rendering Processing PShape or from an immediate-mode rendering Processing procedure. Shapes can be picked precisely using their projection onto the screen, see setPrecision(Frame.Precision). Use traverse() to render all scene-graph shapes or draw() to render a specific one instead.

To set a retained-mode shape use Shape shape = new Shape(Scene scene, PShape shape) or Shape shape = new Shape(Scene scene) and then call Shape.setGraphics(PShape).

Immediate-mode shapes should override Shape.setGraphics(PGraphics), e.g., using an anonymous inner Shape class instance, such as with the following:

...
Shape shape;
void setup() {
  ...
  shape = new Shape(scene) {
    @Override
    protected void setGraphics(PGraphics canvas) {
      //immediate-mode rendering procedure
    }
  };
}

and then render it with:

void draw() {
  // calls visit() on each shape to draw the shape
  scene.traverse();
}

See the DepthOfField example. Some advantages of using shapes are:

  • Same as with attached frames.
  • Shapes are picked precisely using ray-tracing against the pixels of their projection. See setPrecision.
  • Shapes can be set as the scene eye (see setEye(Frame)) which may be useful to depict the viewer in first person camera style.

Interpolators

A frame (and hence a shape) can be animated through a key-frame Catmull-Rom interpolator path. Use code such as the following:

Scene scene;
PShape pshape;
Shape shape;
Interpolator interpolator;
void setup() {
  ...
  shape = new Shape(scene, pshape);
  interpolator = new Interpolator(shape);
  for (int i = 0; i < random(4, 10); i++)
    interpolator.addKeyFrame(scene.randomFrame());
  interpolator.start();
}

which will create a random interpolator path containing [4..10] key-frames. The interpolation is also started. The interpolator path may be drawn with code like this:

...
void draw() {
  scene.traverse();
  scene.drawPath(interpolator, 5);
}

while traverse() will draw the animated shape(s) drawPath(Interpolator, int) will draw the interpolated path too. See the Interpolators example.

HIDs

Setting up a Human Interface Device (hid) (different than the mouse which is provided by default) such as a keyboard or a space-navigator, is a two step process:

  1. Define an hid tracked-frame instance, using an arbitrary name for it (see setTrackedFrame(String, Frame)); and,
  2. Call any interactivity method that take an hid param (such as translate(String, float, float, float), rotate(String, float, float, float) or scale(String, float) following the name convention you defined in 1.

See the SpaceNavigator example.

Observations:

  1. An hid tracked-frame (see trackedFrame(String)) defines in turn an hid default-frame (see defaultFrame(String)) which simply returns the tracked-frame or the scene eye when the hid tracked-frame is null
  2. The hid interactivity methods are implemented in terms of the ones defined previously by simply passing the hid defaultFrame(String) to them.
  3. The default hid is defined with a null String parameter (e.g., scale(float) simply calls scale(null, delta)). The Scene default mouse hid presented in the Frames section is precisely implemented is this manner.
  4. To update an hid tracked-frame using ray-casting call track(String, Point, Frame[]) (detached or attached frames), track(String, Point) (only attached frames) or cast(String, Point) (only for attached frames too). While track(String, Point, Frame[]) and track(String, Point) update the hid tracked-frame synchronously (i.e., they return the hid tracked-frame immediately), cast(String, Point) updates it asynchronously (i.e., it optimally updates the hid tracked-frame during the next call to the traverse() algorithm).

Control

Application control (aka as Post-WIMP interaction styles) refers to interfaces β€œcontaining at least one interaction technique not dependent on classical 2D widgets” [van Dam], such as: tangible interaction, or perceptual and affective computing.

Implementing an application control for a frame is a two step process:

  1. Override the frame method interact(Object...) to parse the gesture into a custom (application) control.
  2. Send gesture data to the frame by calling one of the following scene methods: defaultHIDControl(Object...), control(String, Object...) or control(Frame, Object...).

See the ApplicationControl example.

IK

Drawing

The Scene implements several static drawing functions that complements those already provided by Processing, such as: drawCylinder(PGraphics, int, float, float), drawHollowCylinder(PGraphics, int, float, float, Vector, Vector), drawCone(PGraphics, int, float, float, float, float), drawCone(PGraphics, int, float, float, float, float, float) and drawTorusSolenoid(PGraphics, int, int, float, float).

Drawing functions that take a PGraphics parameter (including the above static ones), such as beginHUD(PGraphics), endHUD(PGraphics), drawAxes(PGraphics, float), drawCross(PGraphics, float, float, float) and drawGrid(PGraphics) among others, can be used to set a (Shape).

Another scene's eye (different than this one) can be drawn with drawEye(Graph). Typical usage include interactive minimaps and visibility culling visualization and debugging.

Installation

Import/update it directly from your PDE. Otherwise download your release and extract it to your sketchbook libraries folder.

Contributors

Thanks goes to these wonderful people (emoji key):


sechaparroc

πŸ“ πŸ› πŸ’» 🎨 πŸ“– πŸ“‹ πŸ’‘ πŸ’΅ πŸ” πŸ€” πŸ“¦ πŸ”Œ πŸ’¬ πŸ‘€ πŸ“’ ⚠️ βœ… πŸ“Ή

Jean Pierre Charalambos

πŸ“ πŸ› πŸ’» 🎨 πŸ“– πŸ“‹ πŸ’‘ πŸ’΅ πŸ” πŸ€” πŸ“¦ πŸ”Œ πŸ’¬ πŸ‘€ πŸ“’ ⚠️ βœ… πŸ“Ή

This project follows the all-contributors specification. Contributions of any kind welcome!

About

License:GNU General Public License v3.0


Languages

Language:Java 96.0%Language:Processing 1.5%Language:GLSL 1.5%Language:CSS 0.6%Language:HTML 0.5%Language:Shell 0.0%