Skip to content

Commit

Permalink
WIP #12: add light, selection effect
Browse files Browse the repository at this point in the history
-Selectables spelling
-Added point light which follows camera
-Set material coloration on selected items for light reflection effect

Note that internal system nodes are currently selectable for testing; in
the next version only DAMCON teams are selectable.
  • Loading branch information
jacobmaxfrank committed Jan 30, 2016
1 parent 1a11189 commit 60d9494
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 28 deletions.
46 changes: 31 additions & 15 deletions src/com/brindyblitz/artemis/engconsole/ui/damcon/Damcon.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@
import javax.media.j3d.*;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector2d;
import javax.vecmath.Vector3d;
import javax.vecmath.*;

import com.brindyblitz.artemis.engconsole.EngineeringConsoleManager;
// See: http://download.java.net/media/java3d/javadoc/1.5.1/
Expand Down Expand Up @@ -51,6 +47,7 @@ public class Damcon implements MouseListener, MouseMotionListener, MouseWheelLis
private PickCanvas pickCanvas;
private SimpleUniverse universe;
private Scene scene = null;
private PointLight light;
private static final boolean WINDOW_HACK = true;

private static final double
Expand All @@ -71,7 +68,7 @@ public class Damcon implements MouseListener, MouseMotionListener, MouseWheelLis
private Map<GridCoord, InternalNode> internalNodes = new HashMap<>();
private Set<InternalConnection> internalConnections = new HashSet<>();
private Map<Integer, InternalTeam> internalTeams = new HashMap<>();
private Map<Node, InternalSelectable> nodesToSelectabls = new HashMap<>();
private Map<Node, InternalSelectable> nodesToSelectables = new HashMap<>(); // TODO: use setUserData() on nodes rather than table lookup?
private static final float PICK_TOLERANCE = 0.1f;

public Damcon(EngineeringConsoleManager engineeringConsoleManager) {
Expand All @@ -81,7 +78,7 @@ public Damcon(EngineeringConsoleManager engineeringConsoleManager) {

if (WINDOW_HACK) {
createUniverseAndScene_HACK();
// TODO: FILE ISSUE > This is a hack to get rid of the extra window. The reason this creates a new window is explained here:
// TODO: HACK > This is a hack to get rid of the extra window. The reason this creates a new window is explained here:
// http://download.java.net/media/java3d/javadoc/1.3.2/com/sun/j3d/utils/universe/Viewer.html
// This might help: https://community.oracle.com/thread/1274674?start=0&tstart=0
JFrame unused_frame = universe.getViewer().getJFrame(0);
Expand All @@ -91,6 +88,8 @@ public Damcon(EngineeringConsoleManager engineeringConsoleManager) {
createUniverseAndScene();
}

addLighting();

loadInternalNodesAndDamconTeams();
loadCorridors();

Expand Down Expand Up @@ -128,7 +127,7 @@ private void loadInternalNodesAndDamconTeams() {
for (VesselNode vn : this.engineeringConsoleManager.getGrid()) {
InternalNode in = new InternalNode(vn);
internalNodes.put(vn.getGridCoord(), in);
nodesToSelectabls.put(in.getShape(), in);
nodesToSelectables.put(in.getShape(), in);
node_branchgroup.addChild(in.getBranchGroup());
}

Expand All @@ -151,7 +150,7 @@ public void onChange() {
if (it == null) {
it = new InternalTeam(damconStatus);
internalTeams.put(damconStatus.getTeamNumber(), it);
nodesToSelectabls.put(it.getShape(), it);
nodesToSelectables.put(it.getShape(), it);
damcon_branchgroup.addChild(it.getBranchGroup());
}
it.updatePos(damconStatus.getX(), damconStatus.getY(), damconStatus.getZ());
Expand Down Expand Up @@ -186,7 +185,20 @@ private void createUniverseAndScene() {

private void createUniverseAndScene_HACK() {
this.universe = new SimpleUniverse();
this.universe.addBranchGraph(scene.getSceneGroup());
this.universe.addBranchGraph(this.scene.getSceneGroup());
}

private void addLighting() {
BranchGroup group = new BranchGroup();
Color3f color = new Color3f(1.0f, 1.0f, 1.0f);
BoundingSphere bounds = new BoundingSphere(new Point3d(0d, 0d, 0d), 5d);

this.light = new PointLight(color, new Point3f(0f, 0f, 0f), new Point3f(1f, 0f, 0f));
this.light.setInfluencingBounds(bounds);
this.light.setCapability(PointLight.ALLOW_POSITION_WRITE);
group.addChild(this.light);

this.universe.addBranchGraph(group);
}

private void addMouseListeners() {
Expand Down Expand Up @@ -224,7 +236,7 @@ private TransformGroup getCamera() {
private static void wireframeifyNonPickableScene(Scene scene, int line_attribute_pattern) {
Appearance wireframe = getWireframeAppearance(line_attribute_pattern);

// TODO: This works for the Artemis OBJ model. If the scene graph has multiple Shape3D nodes, this would need to be set on all of them. Is that necessary or can we guarantee it won't be needed?
// TODO: HACK > This works for the Artemis OBJ model. If the scene graph has multiple Shape3D nodes, this would need to be set on all of them. Is that necessary or can we guarantee it won't be needed?
Enumeration<Node> children = scene.getSceneGroup().getAllChildren();
while (children.hasMoreElements()) {
Node node = children.nextElement();
Expand Down Expand Up @@ -271,11 +283,11 @@ private static Appearance getWireframeAppearance(int line_attributes_pattern) {

private InternalSelectable pick(MouseEvent e) {
// TODO: DAMCON > Use pickAll(). Prioritize as follows:
// DAMCON teams, system nodes, non-system nodes, hallways
// DAMCON teams, system nodes, non-system nodes, hallways (maybe prioritize nodes if DAMCON currently selected)
pickCanvas.setShapeLocation(e);
PickInfo pi = pickCanvas.pickClosest();

return pi == null ? null : nodesToSelectabls.get(pi.getNode());
return pi == null ? null : nodesToSelectables.get(pi.getNode());
}

@Override
Expand All @@ -284,7 +296,7 @@ public void mouseClicked(MouseEvent e) {

if (e.getButton() == 1) {
// Update selection state
for (InternalSelectable i : nodesToSelectabls.values()) {
for (InternalSelectable i : nodesToSelectables.values()) {
i.setSelected(internal != null && i.equals(internal));
}
}
Expand Down Expand Up @@ -382,6 +394,8 @@ public void mouseDragged(MouseEvent e) {
xform.lookAt(new Point3d(yawed_cam_pos.x, yawed_cam_pos.y, yawed_cam_pos.z), new Point3d(0d, 0d, 0d), new_up);
xform.invert(); // Why do we have to invert this?! Who knows?!
camera.setTransform(xform);

this.light.setPosition((float)yawed_cam_pos.x, (float)yawed_cam_pos.y, (float)yawed_cam_pos.z);
}
}
}
Expand All @@ -403,7 +417,7 @@ public void mouseMoved(MouseEvent e) {
InternalSelectable internal = pick(e);

// Update hover state
for (InternalSelectable i : nodesToSelectabls.values()) {
for (InternalSelectable i : nodesToSelectables.values()) {
i.setHovered(internal != null && i.equals(internal));
}
}
Expand Down Expand Up @@ -439,6 +453,8 @@ public void mouseWheelMoved(MouseWheelEvent e) {
// Apply new position to transformation and transformation back to camera
xform.setTranslation(new_cam_pos);
camera.setTransform(xform);

this.light.setPosition((float) new_cam_pos.x, (float) new_cam_pos.y, (float) new_cam_pos.z);
}

//////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public String toString() {
}


// TODO: Billboards
// Icons for systems would be really nice
//////////////////////
// WIP: Billboards? //
//////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
public abstract class InternalSelectable extends Internal {
protected static final float RADIUS = 0.05f;
protected static final float SHININESS = 0f;
protected static final Color3f BLACK = new Color3f(0f, 0f, 0f);
protected static final Color3f BLACK = new Color3f(0f, 0f, 0f), WHITE = new Color3f(1f, 1f, 1f);
private static final float TRANSPARENT = 1f, OPAQUE = 0f;

protected boolean selected = false, hovered = false;
protected float healthPct = 1f;
Expand All @@ -22,22 +23,20 @@ protected Appearance appearanceFromHealthPercentage() {
Appearance app = new Appearance();
app.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ);
app.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
app.setMaterial(new Material(BLACK, getColorFromHealth(this.healthPct), BLACK, BLACK, SHININESS));
// TODO: FILE ISSUE > when hovering, make opaque or circle or something
app.setMaterial(new Material(BLACK, getColorFromHealth(this.healthPct), BLACK, BLACK, SHININESS)); // TODO: PERF > cache material and update on health change?

if (this.visible()) {
TransparencyAttributes transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, 1f);
app.setTransparencyAttributes(transparency);
TransparencyAttributes transparency;
if (!this.visible()) {
transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, TRANSPARENT);
} else if (this.selected) {
TransparencyAttributes ta = new TransparencyAttributes(TransparencyAttributes.NICEST, 0f);
app.setTransparencyAttributes(ta);
transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, OPAQUE);
app.setMaterial(new Material(BLACK, getColorFromHealth(this.healthPct), WHITE, BLACK, SHININESS));
} else if (this.hovered) {
TransparencyAttributes ta = new TransparencyAttributes(TransparencyAttributes.NICEST, 0f);
app.setTransparencyAttributes(ta);
} else {
TransparencyAttributes transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, alpha);
app.setTransparencyAttributes(transparency);
transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, OPAQUE);
} else { // if (this.visible())
transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, alpha);
}
app.setTransparencyAttributes(transparency);
// TODO: > bug here. Transparency of something is jumping on first node selection after launch. Investigate.
// Same if I select a damcon team too, something in depth buffer/render order is changing with pick

Expand Down Expand Up @@ -66,8 +65,15 @@ protected Color3f getColorFromHealth(float pct) {
}

public void setSelected(boolean selected) {
if (selected) {
System.out.println("Selecting " + this);
}

this.selected = selected;
this.sphere.setAppearance(appearanceFromHealthPercentage());

// TODO: >>> selection is only relevant for damcon teams, not nodes, right?
// Need to track who's selected and issue orders on click of system node when selection != null
}

public void setHovered(boolean hovered) {
Expand Down

0 comments on commit 60d9494

Please sign in to comment.