Package org.nlogo.gl.render

Source Code of org.nlogo.gl.render.Renderer3D

// (C) Uri Wilensky. https://github.com/NetLogo/NetLogo

package org.nlogo.gl.render;

import org.nlogo.api.Agent;
import org.nlogo.api.AgentException;
import org.nlogo.api.DrawingInterface;
import org.nlogo.api.Patch3D;
import org.nlogo.api.Turtle;
import org.nlogo.api.Turtle3D;
import org.nlogo.api.ViewSettings;
import org.nlogo.api.World;
import org.nlogo.api.World3D;

import javax.media.opengl.GL;
import java.util.ArrayList;
import java.util.List;

public class Renderer3D
    extends org.nlogo.gl.render.Renderer {
  public Renderer3D(World world,
                    ViewSettings graphicsSettings,
                    DrawingInterface drawing,
                    GLViewSettings glSettings) {
    super(world, graphicsSettings, drawing, glSettings, new ShapeRenderer3D((World3D) world));
  }

  public Renderer3D(Renderer glrenderer) {
    super(glrenderer);
  }

  @Override
  void setClippingPlanes(GL gl) {
    super.setClippingPlanes(gl);
    World3D w = (World3D) world;

    // don't clip in the z-direction with 2D models.
    if (w.worldDepth() > 1) {
      // offset the planes ever so slightly so they don't cut off the tops of the patches
      renderClippingPlane
          (gl, new double[]
              {0.0f, 0.0, 1.0f, (float) (-(w.minPzcor() - 0.5) * WORLD_SCALE) + 0.01f},
              GL.GL_CLIP_PLANE4);
      renderClippingPlane
          (gl, new double[]
              {0.0, 0.0, -1.0, (float) ((w.maxPzcor() + 0.5) * WORLD_SCALE) + 0.01f},
              GL.GL_CLIP_PLANE5);
    }
  }

  @Override
  void disableClippingPlanes(GL gl) {
    super.disableClippingPlanes(gl);
    gl.glDisable(GL.GL_CLIP_PLANE4);
    gl.glDisable(GL.GL_CLIP_PLANE5);
  }

  @Override
  TurtleRenderer createTurtleRenderer(World world) {
    return new TurtleRenderer3D(world, shapeRenderer);
  }

  @Override
  WorldRenderer createWorldRenderer(World world,
                                    PatchRenderer patchRenderer,
                                    DrawingInterface drawing,
                                    TurtleRenderer turtleRenderer,
                                    GLViewSettings settings) {
    return new WorldRenderer3D((World3D) world, (PatchRenderer3D) patchRenderer,
        drawing, (TurtleRenderer3D) turtleRenderer, (LinkRenderer3D) linkRenderer, settings);
  }

  @Override
  PatchRenderer createPatchRenderer(World world,
                                    DrawingInterface drawing) {
    return new PatchRenderer3D((World3D) world, drawing, shapeRenderer);
  }

  @Override
  LinkRenderer createLinkRenderer(World world) {
    return new LinkRenderer3D(world, shapeRenderer);
  }

  @Override
  public ExportRenderer createExportRenderer() {
    return new ExportRenderer3D(this);
  }

  @Override
  void renderWorld(GL gl, World world) {
    gl.glPushMatrix();
    translateWorld(gl, world);

    worldRenderer.renderWorld(gl, renderer.fontSize(), renderer.patchSize());

    gl.glPopMatrix();

    // In the 3D version, we'll render the drawing layer directly from Renderer.render().
    // worldRenderer.renderDrawing( gl ) ;
  }

  @Override
  public void translateWorld(GL gl, World world) {
    World3D w = (World3D) world;

    gl.glTranslated
        (((world.maxPxcor() + world.minPxcor()) / 2.0) * Renderer.WORLD_SCALE,
            ((world.maxPycor() + world.minPycor()) / 2.0) * Renderer.WORLD_SCALE,
            ((w.maxPzcor() + w.minPzcor()) / 2.0) * Renderer.WORLD_SCALE);
  }

  @Override
  double[] getTurtleCoords(Turtle turtle, double height) {
    Turtle3D t = (Turtle3D) turtle;
    double[] coords = new double[]{t.xcor(), t.ycor(), t.zcor()};
    coords[0] = world.wrappedObserverX(coords[0]) * Renderer.WORLD_SCALE;
    coords[1] = world.wrappedObserverY(coords[1]) * Renderer.WORLD_SCALE;
    coords[2] = ((World3D) world).wrappedObserverZ(coords[2]) * Renderer.WORLD_SCALE;

    return coords;
  }

  double[] getPatchCoords(Patch3D patch) {
    double[] coords = new double[]{patch.pxcor(), patch.pycor(), patch.pzcor()};
    coords[0] = world.wrappedObserverX(coords[0]) * Renderer.WORLD_SCALE;
    coords[1] = world.wrappedObserverY(coords[1]) * Renderer.WORLD_SCALE;
    coords[2] = ((World3D) world).wrappedObserverZ(coords[2]) * Renderer.WORLD_SCALE;

    return coords;
  }

  // pick/select objects for context menu
  @Override
  void performPick() {
    List<Agent> agents = new ArrayList<Agent>();
    double[][] ray = generatePickRay(mouseState.point().getX(), (height - mouseState.point().getY()));
    pickTurtles(agents, ray);
    pickLinks(agents, ray);
    pickPatches(agents, ray);
    pickListener.pick(mouseState.point(), agents);
    mouseState.pickRequest_$eq(false);
  }

  double wrapZ(double z) {
    return ((World3D) world).wrapZ(z);
  }

  @Override
  void pickPatches(List<Agent> agents, double[][] ray) {
    if (agents == null) {
      return;
    }

    World3D w = (World3D) world;

    // detect any patches in the pick-ray ( ( Renderer.WORLD_SCALE / 2 )
    // is the offset of the patches plane in the z-axis - jrn)
    double scale = (1 / WORLD_SCALE);
    double deltaz = Math.abs(ray[0][2] - ray[1][2]);
    double deltay = Math.abs(ray[0][1] - ray[1][1]);
    double deltax = Math.abs(ray[0][0] - ray[1][0]);

    double xi = ray[0][0] * scale;
    double yi = ray[0][1] * scale;
    double zi = ray[0][2] * scale;
    double xinc = 0;
    double yinc = 0;
    double zinc = 0;
    double t = 0;
    double min = 0;
    double max = 0;

    if (deltaz >= deltay && deltaz >= deltax) {
      zinc = 1;
      t = 1 / (ray[1][2] - ray[0][2]);
      xinc = (ray[1][0] - ray[0][0]) * t;
      yinc = (ray[1][1] - ray[0][1]) * t;
      min = w.minPzcor();
      max = w.maxPzcor();
      zi = min;
      xi -= xinc * ray[0][2] * scale - (min * xinc);
      yi -= yinc * ray[0][2] * scale - (min * yinc);
    } else if (deltay >= deltax) {
      yinc = 1;
      t = 1 / (ray[1][1] - ray[0][1]);
      xinc = (ray[1][0] - ray[0][0]) * t;
      zinc = (ray[1][2] - ray[0][2]) * t;
      min = w.minPycor();
      max = w.maxPycor();
      yi = min;
      xi -= xinc * ray[0][1] * scale - (min * xinc);
      zi -= zinc * ray[0][1] * scale - (min * zinc);
    } else {
      xinc = 1;
      t = -1 / (ray[0][0] - ray[1][0]);
      yinc = (ray[1][1] - ray[0][1]) * t;
      zinc = (ray[1][2] - ray[0][2]) * t;
      min = w.minPxcor();
      max = w.maxPxcor();
      xi = min;
      yi -= yinc * ray[0][0] * scale - (min * yinc);
      zi -= zinc * ray[0][0] * scale - (min * zinc);
    }

    for (double c = min; c <= max; c++) {
      double x = xi;
      double y = yi;
      double z = zi;

      if ((x < world.maxPxcor() + 0.5) && (x >= world.minPxcor() - 0.5) &&
          (y < world.maxPycor() + 0.5) && (y >= world.minPycor() - 0.5) &&
          (z < w.maxPzcor() + 0.5) && (z >= w.minPzcor() - 0.5)) {
        try {
          agents.add(w.getPatchAt(wrapX(x + w.followOffsetX()),
              wrapY(y + w.followOffsetY()),
              wrapZ(z + w.followOffsetZ())));
        } catch (AgentException e) {
          org.nlogo.util.Exceptions.ignore(e);
        }
      }
      xi += xinc;
      yi += yinc;
      zi += zinc;
    }
  }
}
TOP

Related Classes of org.nlogo.gl.render.Renderer3D

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.