1. Michael Ludwig
  2. ferox

Commits

Michael Ludwig  committed 19ffa35

Intermediate work.

  • Participants
  • Parent commits 7b3dc5c
  • Branches default

Comments (0)

Files changed (40)

File ferox-physics/src/main/java/com/ferox/physics/controller/ForcesTask.java

View file
 // 1. inertia tensor computer (which must be done before any force can be added to a body)
 // 2. gravity force applier
 // 3. force integrator
+// Although see note in SpatialIndexCollisionController. This is the main place
+// that benefits from merging the loop -> maybe I can artificially support
+// auto-merging by calling this the PrepTask that takes preparers that operate
+// on single RigidBody/CollisionBody entities. These can be split into 
+// composable tasks but only iterated through once in this task.
+//
+// The Motion and ConstraintSolving tasks could be similarly combined, although
+// part of the constraint solving task is global... I bet it doesn't make a 
+// big performance dent so let's just keep it in mind but design for maximum
+// cleanliness right now.
 public class ForcesTask implements Task, ParallelAware {
     private static final Set<Class<? extends ComponentData<?>>> COMPONENTS;
     static {

File ferox-physics/src/main/java/com/ferox/physics/controller/SpatialIndexCollisionController.java

View file
         iterator.reset();
     }
 
+    // NOTE: with regards to performance and task creation, there are 
+    // non-zero costs with iterating through the system: content is pulled
+    // from the properties into local instances and then processed (either
+    // directly with getters, or the onSet() method). This means that if
+    // multiple tasks are executed consecutively but access the same component
+    // types, we're doing additional load work.
+    //
+    // It'd be faster to merge those tasks into a single loop. Is this something
+    // I should automate, or something that I should consider when I design my
+    // tasks? I think it's too awkward to automate, although it would be cool.
+    //
+    // 
+
     @Override
     public Task process(EntitySystem system, Job job) {
         // if the index is bounded, update its size so everything is processed
             // FIXME how much does computing the union hurt our performance?
             // FIXME do we want to shrink the extent even when the original extent
             // is large enough? How does that affect query performance?
+
+            // FIXME right now, setTransform() computes updateBounds() for CollisionBody,
+            // which isn't the best -> what if we had a task that just computed
+            // world bounds (like world bounds task in scene module) and it could
+            // report the union as well.
+
+            // Now the only issue is whether we want to duplicate this code, since
+            // both sources need the same functionality but they are definitely not
+            // sharable.  The only place would be if the math module defined the
+            // world bounds result type (we need different tasks because they
+            // process things differently anyways).
             AxisAlignedBox extent = new AxisAlignedBox();
             boolean first = true;
             while (iterator.next()) {

File ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/ContextState.java

View file
+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 package com.ferox.renderer;
 
 /**

File ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/util/geom/Box.java

View file
 
     /**
      * Construct a box centered on its origin, with the given side length. So,
-     * Box(1f) creates a unit cube.
+     * Box(1.0) creates a unit cube.
      * 
      * @param side The side length of the created cube
      * @param mode The storage mode to use for the Box
     }
 
     /**
+     * Construct a box centered on its origin, with the given side lengths along
+     * each local axis.
+     * 
+     * @param xExtent The side length along the x axis
+     * @param yExtent The side length along the y axis
+     * @param zExtent The side length along the z axis
+     * @param mode The storage mode
+     * @return The new geometry
+     * @throws NullPointerException if mode is null
+     * @throws IllegalMonitorStateException if any dimension is negative
+     */
+    public static Geometry create(double xExtent, double yExtent, double zExtent,
+                                  StorageMode mode) {
+        return create(new Vector3(-xExtent / 2, -yExtent / 2, -zExtent / 2),
+                      new Vector3(xExtent / 2, yExtent / 2, zExtent / 2), mode);
+    }
+
+    /**
      * Construct a new Box with the given minimum and maximum points. These
      * points are opposite corners of the box.
      * 

File ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/util/geom/Cylinder.java

View file
+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 package com.ferox.util.geom;
 
 import com.ferox.math.AxisAlignedBox;
             m.setCol(1, v);
             m.setCol(2, u.cross(v).normalize());
 
-            for (int i = 0; i < va.length; i += 3) {
+            Matrix3 n = new Matrix3(m).inverse();
+
+            for (int i = 0; i < va.length; i += 8) {
+                // vertex
                 u.set(va, i);
                 u.mul(m, u);
                 u.get(va, i);
+
+                // normal
+                u.set(va, i + 3);
+                u.mul(u, n);
+                u.get(va, i + 3);
             }
 
             this.indices = new VertexBufferObject(new BufferData(indices), mode);

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/FixedFunctionState.java

View file
+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 package com.ferox.renderer.impl;
 
 import java.util.Arrays;

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/RendererState.java

View file
+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 package com.ferox.renderer.impl;
 
 import java.util.Arrays;

File ferox-renderer/ferox-renderer-lwjgl/src/main/java/com/ferox/renderer/impl/lwjgl/LwjglInputEventAdapter.java

View file
 public class LwjglInputEventAdapter {
     private final MouseKeyEventDispatcher dispatcher;
 
-    private int lastMouseX = Integer.MIN_VALUE;
-    private int lastMouseY = Integer.MIN_VALUE;
+    private final int lastMouseX = Integer.MIN_VALUE;
+    private final int lastMouseY = Integer.MIN_VALUE;
 
     public LwjglInputEventAdapter(MouseKeyEventDispatcher dispatcher) {
         if (dispatcher == null) {
         // Process all incoming keyboard events
         while (Keyboard.next()) {
             KeyEvent.KeyCode keyCode = getKeyCode(Keyboard.getEventKey());
-
             char eventChar = Keyboard.getEventCharacter();
             if (eventChar == Keyboard.CHAR_NONE) {
                 eventChar = KeyEvent.CHAR_UNKNOWN;

File ferox-scene/src/main/java/com/ferox/scene/AbstractPlacedLight.java

View file
  */
 package com.ferox.scene;
 
+import com.lhkbob.entreri.Requires;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
 
  * @author Michael Ludwig
  * @param <T> The component light type
  */
+@Requires(Transform.class)
 public abstract class AbstractPlacedLight<T extends AbstractPlacedLight<T>> extends Light<T> {
     @DefaultDouble(-1.0)
     private DoubleProperty falloffDistance;

File ferox-scene/src/main/java/com/ferox/scene/AmbientLight.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 
 /**
  * AmbientLight represents a source of ambient light in a scene. Ambient lights
  * @author Michael Ludwig
  */
 public final class AmbientLight extends Light<AmbientLight> {
-    /**
-     * The shared TypedId representing AmbientLight.
-     */
-    public static final TypeId<AmbientLight> ID = TypeId.get(AmbientLight.class);
-
     private AmbientLight() {}
 }

File ferox-scene/src/main/java/com/ferox/scene/AtmosphericFog.java

View file
 import com.ferox.math.Const;
 import com.ferox.math.entreri.ColorRGBProperty;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.Unmanaged;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
  */
 public final class AtmosphericFog extends ComponentData<AtmosphericFog> {
     /**
-     * The shared TypedId representing AtmosphericFog.
-     */
-    public static final TypeId<AtmosphericFog> ID = TypeId.get(AtmosphericFog.class);
-
-    /**
      * Falloff represents how the visibility of fog decreases as distance
      * increases. The opacity of the fog, at some distance, can be considered as
      * a floating point number within [0, 1]. When at a distance less than or

File ferox-scene/src/main/java/com/ferox/scene/BlinnPhongMaterial.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
 
  * @author Michael Ludwig
  */
 public final class BlinnPhongMaterial extends Material<BlinnPhongMaterial> {
-    /**
-     * The shared TypedId representing BlinnPhongMaterial.
-     */
-    public static final TypeId<BlinnPhongMaterial> ID = TypeId.get(BlinnPhongMaterial.class);
-
     @DefaultDouble(1.0)
     private DoubleProperty shininess;
 

File ferox-scene/src/main/java/com/ferox/scene/Camera.java

View file
 
 import com.ferox.renderer.Surface;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
+import com.lhkbob.entreri.Requires;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
 import com.lhkbob.entreri.property.ObjectProperty;
  * 
  * @author Michael Ludwig
  */
+@Requires(Transform.class)
 public final class Camera extends ComponentData<Camera> {
-    /**
-     * The shared TypedId instance corresponding to Camera.
-     */
-    public static final TypeId<Camera> ID = TypeId.get(Camera.class);
-
     private ObjectProperty<Surface> surface;
 
     @DefaultDouble(60.0)

File ferox-scene/src/main/java/com/ferox/scene/DecalColorMap.java

View file
 package com.ferox.scene;
 
 import com.ferox.resource.Texture;
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public class DecalColorMap extends TextureMap<DecalColorMap> {
-    /**
-     * TypeId for DecalColorMap.
-     */
-    public static final TypeId<DecalColorMap> ID = TypeId.get(DecalColorMap.class);
-
     private DecalColorMap() {}
 
     @Override

File ferox-scene/src/main/java/com/ferox/scene/DepthOffsetMap.java

View file
 
 import com.ferox.resource.Texture;
 import com.ferox.resource.TextureFormat;
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class DepthOffsetMap extends TextureMap<DepthOffsetMap> {
-    /**
-     * The shared TypedId representing DepthOffsetMap.
-     */
-    public static final TypeId<DepthOffsetMap> ID = TypeId.get(DepthOffsetMap.class);
-
     private DepthOffsetMap() {}
 
     @Override

File ferox-scene/src/main/java/com/ferox/scene/DiffuseColor.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class DiffuseColor extends ColorComponent<DiffuseColor> {
-    /**
-     * The shared TypedId representing DiffuseColor.
-     */
-    public static final TypeId<DiffuseColor> ID = TypeId.get(DiffuseColor.class);
-
     private DiffuseColor() {}
 }

File ferox-scene/src/main/java/com/ferox/scene/DiffuseColorMap.java

View file
 package com.ferox.scene;
 
 import com.ferox.resource.Texture;
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public class DiffuseColorMap extends TextureMap<DiffuseColorMap> {
-    /**
-     * The shared TypedId representing DiffuseColorMap.
-     */
-    public static final TypeId<DiffuseColorMap> ID = TypeId.get(DiffuseColorMap.class);
-
     private DiffuseColorMap() {}
 
     @Override

File ferox-scene/src/main/java/com/ferox/scene/DirectionLight.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
+import com.lhkbob.entreri.Requires;
 import com.lhkbob.entreri.property.BooleanProperty;
 import com.lhkbob.entreri.property.BooleanProperty.DefaultBoolean;
 
  * 
  * @author Michael Ludwig
  */
+@Requires(Transform.class)
 public final class DirectionLight extends Light<DirectionLight> {
-    /**
-     * The shared TypedId representing DirectionLight.
-     */
-    public static final TypeId<DirectionLight> ID = TypeId.get(DirectionLight.class);
-
     @DefaultBoolean(false)
     private BooleanProperty shadowCaster;
 

File ferox-scene/src/main/java/com/ferox/scene/EmittedColor.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class EmittedColor extends ColorComponent<EmittedColor> {
-    /**
-     * The shared TypedId representing EmittedColor.
-     */
-    public static final TypeId<EmittedColor> ID = TypeId.get(EmittedColor.class);
-
     private EmittedColor() {}
 }

File ferox-scene/src/main/java/com/ferox/scene/EmittedColorMap.java

View file
 package com.ferox.scene;
 
 import com.ferox.resource.Texture;
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public class EmittedColorMap extends TextureMap<EmittedColorMap> {
-    /**
-     * The shared TypedId representing DepthOffsetMap.
-     */
-    public static final TypeId<EmittedColorMap> ID = TypeId.get(EmittedColorMap.class);
-
     private EmittedColorMap() {}
 
     @Override

File ferox-scene/src/main/java/com/ferox/scene/InfluenceRegion.java

View file
 import com.ferox.math.Const;
 import com.ferox.math.entreri.AxisAlignedBoxProperty;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.Unmanaged;
 import com.lhkbob.entreri.property.BooleanProperty;
 
+// FIXME requires Transform? I don't think so...
 public final class InfluenceRegion extends ComponentData<InfluenceRegion> {
-    /**
-     * TypeId for InfluenceRegion component type.
-     */
-    public static final TypeId<InfluenceRegion> ID = TypeId.get(InfluenceRegion.class);
-
     private AxisAlignedBoxProperty bounds;
     private BooleanProperty negate;
 

File ferox-scene/src/main/java/com/ferox/scene/Influences.java

View file
 import com.lhkbob.entreri.Entity;
 import com.lhkbob.entreri.Factory;
 import com.lhkbob.entreri.PropertyFactory;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.property.ObjectProperty;
 
 public final class Influences extends ComponentData<Influences> {
-    /**
-     * TypeId for Influences Component type
-     */
-    public static final TypeId<Influences> ID = TypeId.get(Influences.class);
-
     @Factory(SetFactory.class)
     private ObjectProperty<Set<Entity>> entities;
 

File ferox-scene/src/main/java/com/ferox/scene/NormalMap.java

View file
 import com.ferox.resource.Texture;
 import com.ferox.resource.TextureFormat;
 import com.ferox.resource.VertexAttribute;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.property.ObjectProperty;
 
 /**
  * @author Michael Ludwig
  */
 public final class NormalMap extends TextureMap<NormalMap> {
-    /**
-     * The shared TypedId representing NormalMap.
-     */
-    public static final TypeId<NormalMap> ID = TypeId.get(NormalMap.class);
-
     private ObjectProperty<VertexAttribute> tangentVectors;
 
     private NormalMap() {}

File ferox-scene/src/main/java/com/ferox/scene/PointLight.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class PointLight extends AbstractPlacedLight<PointLight> {
-    /**
-     * The shared TypedId representing PointLight.
-     */
-    public static final TypeId<PointLight> ID = TypeId.get(PointLight.class);
-
     private PointLight() {}
 }

File ferox-scene/src/main/java/com/ferox/scene/Renderable.java

View file
 import com.ferox.resource.VertexBufferObject;
 import com.ferox.util.geom.Geometry;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
+import com.lhkbob.entreri.Requires;
 import com.lhkbob.entreri.Unmanaged;
 import com.lhkbob.entreri.property.IntProperty;
 import com.lhkbob.entreri.property.ObjectProperty;
  * 
  * @author Michael Ludwig
  */
+@Requires(Transform.class)
 public final class Renderable extends ComponentData<Renderable> {
-    /**
-     * The shared TypedId representing Renderable.
-     */
-    public static final TypeId<Renderable> ID = TypeId.get(Renderable.class);
-
     private ObjectProperty<VertexAttribute> vertices;
     private ObjectProperty<VertexBufferObject> indices;
     private ObjectProperty<PolygonType> polyType;

File ferox-scene/src/main/java/com/ferox/scene/SpecularColor.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class SpecularColor extends ColorComponent<SpecularColor> {
-    /**
-     * The shared TypedId representing SpecularColor.
-     */
-    public static final TypeId<SpecularColor> ID = TypeId.get(SpecularColor.class);
-
     private SpecularColor() {}
 }

File ferox-scene/src/main/java/com/ferox/scene/SpecularColorMap.java

View file
 package com.ferox.scene;
 
 import com.ferox.resource.Texture;
-import com.lhkbob.entreri.TypeId;
 
 /**
  * <p>
  * @author Michael Ludwig
  */
 public final class SpecularColorMap extends TextureMap<SpecularColorMap> {
-    /**
-     * The shared TypedId representing DepthOffsetMap.
-     */
-    public static final TypeId<SpecularColorMap> ID = TypeId.get(SpecularColorMap.class);
-
     private SpecularColorMap() {}
 
     @Override

File ferox-scene/src/main/java/com/ferox/scene/SpotLight.java

View file
  */
 package com.ferox.scene;
 
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.property.BooleanProperty;
 import com.lhkbob.entreri.property.BooleanProperty.DefaultBoolean;
 import com.lhkbob.entreri.property.DoubleProperty;
  * @author Michael Ludwig
  */
 public final class SpotLight extends AbstractPlacedLight<SpotLight> {
-    /**
-     * The shared TypedId representing SpotLight.
-     */
-    public static final TypeId<SpotLight> ID = TypeId.get(SpotLight.class);
-
     @DefaultDouble(30.0)
     private DoubleProperty cutoffAngle;
 

File ferox-scene/src/main/java/com/ferox/scene/Transform.java

View file
 import com.ferox.math.entreri.Matrix4Property;
 import com.ferox.math.entreri.Matrix4Property.DefaultMatrix4;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.Unmanaged;
 
 /**
  * @author Michael Ludwig
  */
 public final class Transform extends ComponentData<Transform> {
-    /**
-     * The shared TypedId representing Transform.
-     */
-    public static final TypeId<Transform> ID = TypeId.get(Transform.class);
-
     // the identity matrix
     @DefaultMatrix4(m00 = 1.0, m01 = 0.0, m02 = 0.0, m03 = 0.0, m10 = 0.0, m11 = 1.0,
                     m12 = 0.0, m13 = 0.0, m20 = 0.0, m21 = 0.0, m22 = 1.0, m23 = 0.0,

File ferox-scene/src/main/java/com/ferox/scene/Transparent.java

View file
 package com.ferox.scene;
 
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
 
  * @author Michael Ludwig
  */
 public final class Transparent extends ComponentData<Transparent> {
-    /**
-     * The shared TypedId representing Transparent.
-     */
-    public static final TypeId<Transparent> ID = TypeId.get(Transparent.class);
-
     @DefaultDouble(0.5)
     private DoubleProperty opacity;
 

File ferox-scene/src/main/java/com/ferox/scene/controller/SceneBoundsResult.java

View file
+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.ferox.scene.controller;
+
+import com.ferox.math.AxisAlignedBox;
+import com.ferox.math.Const;
+import com.lhkbob.entreri.Result;
+
+public class SceneBoundsResult implements Result {
+    private final AxisAlignedBox sceneBounds;
+
+    public SceneBoundsResult(@Const AxisAlignedBox bounds) {
+        sceneBounds = new AxisAlignedBox(bounds);
+    }
+
+    @Const
+    public AxisAlignedBox getSceneBounds() {
+        return sceneBounds;
+    }
+
+    @Override
+    public boolean isSingleton() {
+        return true;
+    }
+}

File ferox-scene/src/main/java/com/ferox/scene/controller/SpatialIndexController.java

View file
 import com.lhkbob.entreri.SimpleController;
 
 public class SpatialIndexController extends SimpleController {
-    private SpatialIndex<Entity> index;
+    private final SpatialIndex<Entity> index;
 
     // FIXME: add a setter, too
     public SpatialIndexController(SpatialIndex<Entity> index) {
 
     @Override
     public void preProcess(double dt) {
+        // FIXME add a way to adjust the bounds of a SpatialIndex, and have this
+        // listen for SceneBoundsResults and update the index so we don't lose
+        // objects inappropriately
         index.clear(true);
     }
 

File ferox-scene/src/main/java/com/ferox/scene/controller/WorldBoundsController.java

View file
         ComponentIterator it = new ComponentIterator(getEntitySystem()).addRequired(renderable)
                                                                        .addRequired(transform);
 
+        AxisAlignedBox sceneBounds = new AxisAlignedBox();
+        boolean first = true;
+
         while (it.next()) {
             worldBounds.transform(renderable.getLocalBounds(), transform.getMatrix());
             renderable.setWorldBounds(worldBounds);
+
+            if (first) {
+                sceneBounds.set(worldBounds);
+            } else {
+                sceneBounds.union(worldBounds);
+            }
         }
+
+        getEntitySystem().getControllerManager()
+                         .report(new SceneBoundsResult(sceneBounds));
     }
 }

File ferox-scene/src/main/java/com/ferox/scene/controller/ffp/FixedFunctionRenderController.java

View file
 import com.ferox.renderer.Framework;
 import com.ferox.renderer.HardwareAccessLayer;
 import com.ferox.renderer.RenderCapabilities;
+import com.ferox.renderer.Renderer.DrawStyle;
 import com.ferox.renderer.Surface;
 import com.ferox.renderer.Task;
 import com.ferox.scene.Camera;
     private final Queue<Future<Void>> previousFrame;
 
     public FixedFunctionRenderController(Framework framework) {
-        this(framework, 512);
+        this(framework, 1024);
     }
 
     public FixedFunctionRenderController(Framework framework, int shadowMapSize) {
     @Override
     @SuppressWarnings("unchecked")
     public void process(double dt) {
+
+        // Block until previous frame is completed to prevent the main thread
+        // from getting too ahead of the rendering thread.
+        // - We do the blocking at the end so that this thread finishes all
+        // processing before waiting on the rendering thread.
+        long now = System.nanoTime();
+        while (!previousFrame.isEmpty()) {
+            Future<Void> f = previousFrame.poll();
+            try {
+                f.get();
+            } catch (Exception e) {
+                throw new RuntimeException("Previous frame failed", e);
+            }
+        }
+        blocktime += (System.nanoTime() - now);
+
         Camera camera = getEntitySystem().createDataInstance(Camera.ID);
 
         // first cache all shadow map frustums so any view can easily prepare a texture
+        // FIXME must properly thread-safety this because we start the reset
+        // before the previous frame has completed use of it
+        // - I'm not sure but this might be the sole problem with the deadlock, or just the crash
+        //   When it doesn't crash something else might still cause it to freeze up entirely
+        //   including the rest of the OS which is bad
         shadowMap.reset();
         for (PVSResult visible : pvs) {
             // cacheShadowScene properly ignores PVSResults that aren't for lights
             }
         }
 
-        // Block until previous frame is completed to prevent the main thread
-        // from getting too ahead of the rendering thread.
-        // - We do the blocking at the end so that this thread finishes all
-        // processing before waiting on the rendering thread.
-        long now = System.nanoTime();
-        while (!previousFrame.isEmpty()) {
-            Future<Void> f = previousFrame.poll();
-            try {
-                f.get();
-            } catch (Exception e) {
-                throw new RuntimeException("Previous frame failed", e);
-            }
-        }
-        blocktime += (System.nanoTime() - now);
         previousFrame.addAll(thisFrame);
     }
 
                     FixedFunctionRenderer ffp = ctx.getFixedFunctionRenderer();
                     // FIXME clear color should be configurable somehow
                     ffp.clear(true, true, true, new Vector4(0, 0, 0, 1.0), 1, 0);
-
+                    ffp.setDrawStyle(DrawStyle.SOLID, DrawStyle.SOLID);
                     rootNode.render(access, new AppliedEffects());
 
                     //                    Frustum twoD = new Frustum(true,
                     //
                     //                    Geometry g = Rectangle.create(0, 250, 0, 250);
                     //                    ffp.setVertices(g.getVertices());
+                    //                    ffp.setTextureCoordinates(0, g.getTextureCoordinates());
                     //                    if (g.getIndices() == null) {
                     //                        ffp.render(g.getPolygonType(), g.getIndexOffset(),
                     //                                   g.getIndexCount());

File ferox-scene/src/main/java/com/ferox/scene/controller/ffp/ShadowMapCache.java

View file
         } else {
             access.setActiveSurface(origSurface);
         }
+
+        // FIXME race condition on shutdown exists if the orig surface is
+        // destroyed while rendering to the shadow map, if the map is on a pbuffer
         access.getCurrentContext().getFixedFunctionRenderer().setCurrentState(origState);
 
         return shadowMap.getDepthBuffer();

File ferox-scene/src/main/java/com/ferox/scene/controller/light/ShadowFrustumController.java

View file
  */
 package com.ferox.scene.controller.light;
 
+import com.ferox.math.AxisAlignedBox;
+import com.ferox.math.Const;
 import com.ferox.math.Matrix4;
+import com.ferox.math.Vector3;
 import com.ferox.math.bounds.Frustum;
+import com.ferox.renderer.Surface;
+import com.ferox.scene.Camera;
 import com.ferox.scene.DirectionLight;
 import com.ferox.scene.SpotLight;
 import com.ferox.scene.Transform;
 import com.ferox.scene.controller.FrustumResult;
+import com.ferox.scene.controller.SceneBoundsResult;
+import com.lhkbob.entreri.Component;
 import com.lhkbob.entreri.ComponentIterator;
+import com.lhkbob.entreri.Result;
 import com.lhkbob.entreri.SimpleController;
 
 public class ShadowFrustumController extends SimpleController {
     private static final Matrix4 DEFAULT_MAT = new Matrix4().setIdentity();
 
+    private SceneBoundsResult sceneBounds;
+    private FrustumResult camera;
+
+    @Override
+    public void report(Result r) {
+        if (r instanceof SceneBoundsResult) {
+            sceneBounds = (SceneBoundsResult) r;
+        } else if (r instanceof FrustumResult) {
+            FrustumResult fr = (FrustumResult) r;
+            if (fr.getSource().getTypeId() == Camera.ID) {
+                // keep the frustum that has the biggest volume, but most
+                // likely there will only be one camera ever
+                if (camera == null || frustumVolume(camera.getFrustum()) < frustumVolume(fr.getFrustum())) {
+                    camera = fr;
+                }
+            }
+        }
+    }
+
+    @Override
+    public void preProcess(double dt) {
+        sceneBounds = null;
+        camera = null;
+    }
+
+    private double frustumVolume(Frustum f) {
+        double dx = Math.abs(f.getFrustumRight() - f.getFrustumLeft());
+        double dy = Math.abs(f.getFrustumTop() - f.getFrustumBottom());
+        double dz = Math.abs(f.getFrustumFar() - f.getFrustumNear());
+        return dx * dy * dz;
+    }
+
     @Override
     public void process(double dt) {
+        if (camera == null) {
+            // if there's nothing being rendered into, then there's no point in
+            // rendering shadows (and we don't have the info to compute a DL
+            // frustum anyway).
+            return;
+        }
+
         // Process DirectionLights
         DirectionLight dl = getEntitySystem().createDataInstance(DirectionLight.ID);
         Transform t = getEntitySystem().createDataInstance(Transform.ID);
     }
 
     private Frustum computeFrustum(DirectionLight light, Transform t) {
-        Frustum f = new Frustum(true, -15, 15, -15, 15, 0, 50);
-        if (t.isEnabled()) {
-            f.setOrientation(t.getMatrix());
+        // Implement basic frustum improvement techniques from:
+        // http://msdn.microsoft.com/en-us/library/windows/desktop/ee416324(v=vs.85).aspx
+        Frustum v = camera.getFrustum();
+        Surface s = ((Component<Camera>) camera.getSource()).getData().getSurface();
+        Matrix4 lightMatrix = (t.isEnabled() ? t.getMatrix() : DEFAULT_MAT);
+
+        Frustum f = new Frustum(true, -1, 1, -1, 1, -1, 1);
+        f.setOrientation(new Vector3(), lightMatrix.getUpperMatrix());
+
+        Matrix4 toLight = f.getViewMatrix();
+
+        // We transform the view frustum into light space and compute the min
+        // and max x/y values of its 8 corners in light space
+        AxisAlignedBox extent = computeViewBounds(toLight, v);
+
+        // If we have scene bounds, tighten the near and far planes to be the
+        // z-projections of the bounds in light space
+        if (sceneBounds != null) {
+            clampToBounds(toLight, sceneBounds.getSceneBounds(), extent);
+        }
+
+        // Update values to fix texel shimmering
+        // FIXME this doesn't work, the main problem is that rotations of the camera can change
+        // the ratio of texel space to world space changes, which causes shimmering
+        // even if we floor the extents. The solution is apparenty to use a bounding
+        // sphere over the 8 points of the view frustum so its size is rotation
+        // invariant
+        double worldArea = (v.getFrustumRight() - v.getFrustumLeft()) * (v.getFrustumTop() - v.getFrustumBottom());
+        //        double worldUnitsPerTexel = worldArea / (s.getWidth() * s.getHeight());
+        //        double worldArea = (extent.max.x - extent.min.x) * (extent.max.y - extent.min.y);
+        double worldUnitsPerTexel = worldArea / (1024 * 1024); // FIXME buffer size
+
+        extent.min.x = Math.floor(extent.min.x / worldUnitsPerTexel) * worldUnitsPerTexel;
+        extent.min.y = Math.floor(extent.min.y / worldUnitsPerTexel) * worldUnitsPerTexel;
+        extent.max.x = Math.floor(extent.max.x / worldUnitsPerTexel) * worldUnitsPerTexel;
+        extent.max.y = Math.floor(extent.max.y / worldUnitsPerTexel) * worldUnitsPerTexel;
+
+        //                extent.min.scale(1 / worldUnitsPerTexel);
+        //        extent.min.floor();
+        //                extent.min.scale(worldUnitsPerTexel);
+
+        //                extent.max.scale(1 / worldUnitsPerTexel);
+        //        extent.max.floor();
+        //                extent.max.scale(worldUnitsPerTexel);
+
+        f.setFrustum(true, extent.min.x, extent.max.x, extent.min.y, extent.max.y,
+                     extent.min.z, extent.max.z);
+
+        return f;
+    }
+
+    private void clampToBounds(@Const Matrix4 lightMatrix, @Const AxisAlignedBox scene,
+                               AxisAlignedBox lightExtent) {
+        Vector3[] sceneCorners = new Vector3[8];
+        for (int i = 0; i < sceneCorners.length; i++) {
+            Vector3 c = new Vector3();
+            c.x = (i & 0x1) == 0 ? scene.min.x : scene.max.x;
+            c.y = (i & 0x2) == 0 ? scene.min.y : scene.max.y;
+            c.z = (i & 0x4) == 0 ? scene.min.z : scene.max.z;
+            c.transform(lightMatrix, c);
+            sceneCorners[i] = c;
+        }
+
+        // 12 edges
+        int[] e1 = new int[] {0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6};
+        int[] e2 = new int[] {1, 2, 4, 3, 5, 3, 6, 7, 5, 6, 7, 7};
+
+        double[] intersections = new double[12 * 4];
+        for (int i = 0; i < e1.length; i++) {
+            intersections[i * 4 + 0] = intersection(sceneCorners[e1[i]].x,
+                                                    sceneCorners[e1[i]].z,
+                                                    sceneCorners[e2[i]].x,
+                                                    sceneCorners[e2[i]].z,
+                                                    lightExtent.min.x);
+            intersections[i * 4 + 1] = intersection(sceneCorners[e1[i]].x,
+                                                    sceneCorners[e1[i]].z,
+                                                    sceneCorners[e2[i]].x,
+                                                    sceneCorners[e2[i]].z,
+                                                    lightExtent.max.x);
+            intersections[i * 4 + 2] = intersection(sceneCorners[e1[i]].y,
+                                                    sceneCorners[e1[i]].z,
+                                                    sceneCorners[e2[i]].y,
+                                                    sceneCorners[e2[i]].z,
+                                                    lightExtent.min.y);
+            intersections[i * 4 + 3] = intersection(sceneCorners[e1[i]].y,
+                                                    sceneCorners[e1[i]].z,
+                                                    sceneCorners[e2[i]].y,
+                                                    sceneCorners[e2[i]].z,
+                                                    lightExtent.max.y);
+        }
+
+        lightExtent.min.z = Double.POSITIVE_INFINITY;
+        lightExtent.max.z = Double.NEGATIVE_INFINITY;
+
+        for (int i = 0; i < intersections.length; i++) {
+            if (Double.isNaN(intersections[i])) {
+                // edge intersection outside of bounds, so fallback to vertex
+                lightExtent.min.z = Math.min(lightExtent.min.z, sceneCorners[e1[i / 4]].z);
+                lightExtent.max.z = Math.max(lightExtent.max.z, sceneCorners[e1[i / 4]].z);
+                lightExtent.min.z = Math.min(lightExtent.min.z, sceneCorners[e2[i / 4]].z);
+                lightExtent.max.z = Math.max(lightExtent.max.z, sceneCorners[e2[i / 4]].z);
+            } else {
+                lightExtent.min.z = Math.min(lightExtent.min.z, intersections[i]);
+                lightExtent.max.z = Math.max(lightExtent.max.z, intersections[i]);
+            }
+        }
+    }
+
+    private double intersection(double ex1, double ey1, double ex2, double ey2, double lx) {
+        if (lx < Math.min(ex1, ex2) || lx > Math.max(ex1, ex2)) {
+            // out of valid intersection range
+            return Double.NaN;
         } else {
-            f.setOrientation(DEFAULT_MAT);
+            // application of slope-intersection, here e1 and e2 are two-dimensional
+            // points in the projected plane of the current test (i.e. xz or yz)
+            return (ey2 - ey1) / (ex2 - ex1) * (lx - ex1) + ey1;
         }
-        return f;
+    }
+
+    private AxisAlignedBox computeViewBounds(@Const Matrix4 lightMatrix, Frustum f) {
+        AxisAlignedBox extent = new AxisAlignedBox(new Vector3(Double.POSITIVE_INFINITY,
+                                                               Double.POSITIVE_INFINITY,
+                                                               Double.POSITIVE_INFINITY),
+                                                   new Vector3(Double.NEGATIVE_INFINITY,
+                                                               Double.NEGATIVE_INFINITY,
+                                                               Double.NEGATIVE_INFINITY));
+
+        for (int i = 0; i < 8; i++) {
+            Vector3 c = new Vector3();
+            c.x = (i & 0x1) == 0 ? f.getFrustumLeft() : f.getFrustumRight();
+            c.y = (i & 0x2) == 0 ? f.getFrustumBottom() : f.getFrustumTop();
+            c.z = (i & 0x4) == 0 ? f.getFrustumNear() : f.getFrustumFar();
+            if (!f.isOrthogonalProjection()) {
+                c.x *= c.z / f.getFrustumNear();
+                c.y *= c.z / f.getFrustumNear();
+            }
+
+            Vector3 w = new Vector3(f.getLocation());
+            w.addScaled(c.x, new Vector3().cross(f.getDirection(), f.getUp()).normalize())
+             .addScaled(c.y, f.getUp()).addScaled(c.z, f.getDirection());
+            w.transform(lightMatrix, w);
+
+            extent.min.x = Math.min(w.x, extent.min.x);
+            extent.max.x = Math.max(w.x, extent.max.x);
+            extent.min.y = Math.min(w.y, extent.min.y);
+            extent.max.y = Math.max(w.y, extent.max.y);
+            extent.min.z = Math.min(w.z, extent.min.z);
+            extent.max.z = Math.max(w.z, extent.max.z);
+        }
+
+        return extent;
     }
 
     private Frustum computeFrustum(SpotLight light, Transform t) {

File ferox-test/src/main/java/com/ferox/physics/PhysicsApplicationStub.java

View file
 import com.lhkbob.entreri.SimpleController;
 
 public class PhysicsApplicationStub extends ApplicationStub {
-    protected static final int BOUNDS = 100;
+    protected static final int BOUNDS = 50;
     protected static final double MARGIN = .05;
 
     protected static final AxisAlignedBox worldBounds = new AxisAlignedBox(new Vector3(-2 * BOUNDS - 1,
     private static final double MIN_PHI = Math.PI / 12.0;
 
     private static final double MIN_ZOOM = 1.0;
-    private static final double MAX_ZOOM = 30.0;
+    private static final double MAX_ZOOM = BOUNDS;
 
     private static final double ANGLE_RATE = Math.PI / 4.0;
     private static final double ZOOM_RATE = 10.0;
     protected void init(OnscreenSurface surface) {
         // physics handling
         system.getControllerManager()
-              .addController(new com.ferox.physics.controller.ForcesController());
+              .addController(new com.ferox.physics.controller.ForcesTask());
 
         //        system.getControllerManager().addController(new SpatialIndexCollisionController(new com.ferox.math.bounds.QuadTree<Entity>(worldBounds, 6), new DefaultCollisionAlgorithmProvider()));
         //        system.getControllerManager().addController(new SpatialIndexCollisionController(new com.ferox.math.bounds.SimpleSpatialIndex<Entity>(), new DefaultCollisionAlgorithmProvider()));
                                                                  new DefaultCollisionAlgorithmProvider()));
 
         system.getControllerManager()
-              .addController(new com.ferox.physics.controller.ConstraintSolvingController());
+              .addController(new com.ferox.physics.controller.ConstraintSolvingTask());
         system.getControllerManager()
-              .addController(new com.ferox.physics.controller.MotionController());
+              .addController(new com.ferox.physics.controller.MotionTask());
 
         system.getControllerManager().addController(new TransformController());
 
         zoom = (MAX_ZOOM + MIN_ZOOM) / 2.0;
 
         camera = system.addEntity();
-        camera.add(Camera.ID).getData().setSurface(surface)
-              .setZDistances(1.0, 6 * BOUNDS);
+        camera.add(Camera.ID).getData().setSurface(surface).setZDistances(1.0, BOUNDS);
         camera.add(Transform.ID);
         updateCameraOrientation();
     }

File ferox-test/src/main/java/com/ferox/physics/PhysicsTest.java

View file
 import com.ferox.math.ColorRGB;
 import com.ferox.math.Matrix4;
 import com.ferox.math.Vector3;
+import com.ferox.math.Vector4;
 import com.ferox.physics.collision.CollisionBody;
 import com.ferox.physics.dynamics.RigidBody;
 import com.ferox.renderer.OnscreenSurface;
 
         // shapes
         Geometry box = Box.create(2 + 2 * MARGIN, COMPILE_TYPE);
-        //        Geometry sphere = Sphere.create(1 + MARGIN, 8, COMPILE_TYPE);
+        //        Geometry sphere = Sphere.create(1 + MARGIN, 32, COMPILE_TYPE);
 
         com.ferox.physics.collision.Shape boxShape = new com.ferox.physics.collision.shape.Box(2,
                                                                                                2,
                     e.add(CollisionBody.ID)
                      .getData()
                      .setShape(physShape)
-                     .setTransform(new Matrix4(1,
-                                               0,
-                                               0,
-                                               (SCALE_X + 2 * MARGIN) * x + rx + startX,
-                                               0,
-                                               1,
-                                               0,
-                                               (SCALE_Y + 2 * MARGIN) * y + ry + startY,
-                                               0,
-                                               0,
-                                               1,
-                                               (SCALE_Z + 2 * MARGIN) * z + rz + startZ,
-                                               0,
-                                               0,
-                                               0,
-                                               1));
+                     .setTransform(new Matrix4().setIdentity()
+                                                .setCol(3,
+                                                        new Vector4((SCALE_X + 2 * MARGIN) * x + rx + startX,
+                                                                    (SCALE_Y + 2 * MARGIN) * y + ry + startY,
+                                                                    (SCALE_Z + 2 * MARGIN) * z + rz + startZ,
+                                                                    1)));
                     e.add(RigidBody.ID).getData().setMass(1.0);
                 }
             }
         }
 
         // some walls
-        Geometry bottomWall = Box.create(BOUNDS + 2 * MARGIN, COMPILE_TYPE);
+        Geometry bottomWall = Box.create(BOUNDS + 2 * MARGIN, 1, BOUNDS + 2 * MARGIN,
+                                         COMPILE_TYPE);
         Entity wall = system.addEntity();
         wall.add(Renderable.ID)
             .getData()
 
         wall.add(CollisionBody.ID)
             .getData()
-            .setShape(new com.ferox.physics.collision.shape.Box(BOUNDS, BOUNDS, BOUNDS))
-            .setTransform(new Matrix4(1,
-                                      0,
-                                      0,
-                                      0,
-                                      0,
-                                      1,
-                                      0,
-                                      -BOUNDS / 2,
-                                      0,
-                                      0,
-                                      1,
-                                      0,
-                                      0,
-                                      0,
-                                      0,
-                                      1));
+            .setShape(new com.ferox.physics.collision.shape.Box(BOUNDS, 1, BOUNDS))
+            .setTransform(new Matrix4().setIdentity()
+                                       .setCol(3, new Vector4(0, -.5, 0, 1)));
 
         // ambient light
         system.addEntity().add(AmbientLight.ID).getData()
         point.add(PointLight.ID).getData().setColor(new ColorRGB(0.5, 0.5, 0.5));
         point.add(Transform.ID)
              .getData()
-             .setMatrix(new Matrix4(1,
-                                    0,
-                                    0,
-                                    BOUNDS / 2,
-                                    0,
-                                    1,
-                                    0,
-                                    BOUNDS / 2,
-                                    0,
-                                    0,
-                                    1,
-                                    BOUNDS / 2,
-                                    0,
-                                    0,
-                                    0,
-                                    1));
+             .setMatrix(new Matrix4().setIdentity().setCol(3,
+                                                           new Vector4(BOUNDS / 2,
+                                                                       BOUNDS / 2,
+                                                                       BOUNDS / 2,
+                                                                       1)));
 
         // a directed light, which casts shadows
         Entity inf = system.addEntity();
            .setShadowCaster(true);
         inf.add(Transform.ID)
            .getData()
-           .setMatrix(new Matrix4().lookAt(new Vector3(), new Vector3(15, 15, 15),
+           .setMatrix(new Matrix4().lookAt(new Vector3(), new Vector3(0, 15, 15),
                                            new Vector3(0, 1, 0)));
     }
 

File ferox-test/src/main/java/com/ferox/scene/controller/ffp/SimpleTest.java

View file
 import com.ferox.renderer.Framework;
 import com.ferox.renderer.OnscreenSurface;
 import com.ferox.renderer.OnscreenSurfaceOptions;
-import com.ferox.renderer.OnscreenSurfaceOptions.MultiSampling;
 import com.ferox.renderer.impl.jogl.JoglFramework;
 import com.ferox.renderer.impl.lwjgl.LwjglFramework;
 import com.ferox.resource.VertexBufferObject.StorageMode;
 import com.ferox.scene.BlinnPhongMaterial;
 import com.ferox.scene.Camera;
 import com.ferox.scene.DiffuseColor;
+import com.ferox.scene.DirectionLight;
 import com.ferox.scene.InfluenceRegion;
 import com.ferox.scene.PointLight;
 import com.ferox.scene.Renderable;
 import com.ferox.scene.controller.VisibilityController;
 import com.ferox.scene.controller.WorldBoundsController;
 import com.ferox.scene.controller.light.LightGroupController;
+import com.ferox.scene.controller.light.ShadowFrustumController;
 import com.ferox.util.geom.Box;
 import com.ferox.util.geom.Geometry;
 import com.ferox.util.geom.Sphere;
 public class SimpleTest {
     public static final boolean LWJGL = true;
 
+    public static final double BOUNDS = 200;
+
     public static void main(String[] args) {
         Framework framework = (LWJGL ? LwjglFramework.create() : JoglFramework.create());
+        System.out.println(framework.getCapabilities().getFboSupport());
         OnscreenSurface surface = framework.createSurface(new OnscreenSurfaceOptions().setWidth(800)
                                                                                       .setHeight(600)
                                                                                       //            .setFullscreenMode(new DisplayMode(1440, 900, PixelFormat.RGB_24BIT))
-                                                                                      .setMultiSampling(MultiSampling.FOUR_X)
+                                                                                      //                                                                                      .setMultiSampling(MultiSampling.FOUR_X)
                                                                                       .setResizable(false));
-        surface.setVSyncEnabled(true);
+        //        surface.setVSyncEnabled(true);
 
         EntitySystem system = new EntitySystem();
 
         Entity camera = system.addEntity();
-        camera.add(Transform.ID).getData()
-              .setMatrix(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 150, 0, 0, 0, 1));
+        camera.add(Transform.ID)
+              .getData()
+              .setMatrix(new Matrix4(-1,
+                                     0,
+                                     0,
+                                     0,
+                                     0,
+                                     1,
+                                     0,
+                                     0,
+                                     0,
+                                     0,
+                                     -1,
+                                     .9 * BOUNDS,
+                                     0,
+                                     0,
+                                     0,
+                                     1));
         camera.add(Camera.ID).getData().setSurface(surface).setZDistances(0.1, 1200)
               .setFieldOfView(75);
 
              .setLocalBounds(b.getBounds())
              .setIndices(b.getPolygonType(), b.getIndices(), b.getIndexOffset(),
                          b.getIndexCount());
-            if (Math.random() < .9) {
-                e.add(BlinnPhongMaterial.ID).getData().setNormals(b.getNormals());
-            }
+            //            if (Math.random() < .9) {
+            e.add(BlinnPhongMaterial.ID).getData().setNormals(b.getNormals());
+            //            }
             e.add(DiffuseColor.ID).getData().setColor(c);
             e.add(Transform.ID)
              .getData()
              .setMatrix(new Matrix4(1,
                                     0,
                                     0,
-                                    Math.random() * 200 - 100,
+                                    Math.random() * BOUNDS - BOUNDS / 2,
                                     0,
                                     1,
                                     0,
-                                    Math.random() * 200 - 100,
+                                    Math.random() * BOUNDS - BOUNDS / 2,
                                     0,
                                     0,
                                     1,
-                                    Math.random() * 200 - 100,
+                                    Math.random() * BOUNDS - BOUNDS / 2,
                                     0,
                                     0,
                                     0,
 
         System.out.println("Approximate total polygons / frame: " + totalpolys);
 
-        for (int i = 0; i < 20; i++) {
+        for (int i = 0; i < 5; i++) {
             double falloff = 100.0 + Math.random() * 40;
 
             Entity light = system.addEntity();
                  .setMatrix(new Matrix4(1,
                                         0,
                                         0,
-                                        Math.random() * 200 - 100,
+                                        Math.random() * BOUNDS - BOUNDS / 2,
                                         0,
                                         1,
                                         0,
-                                        Math.random() * 200 - 100,
+                                        Math.random() * BOUNDS - BOUNDS / 2,
                                         0,
                                         0,
                                         1,
-                                        Math.random() * 200 - 100,
+                                        Math.random() * BOUNDS - BOUNDS / 2,
                                         0,
                                         0,
                                         0,
         system.addEntity().add(AmbientLight.ID).getData()
               .setColor(new ColorRGB(0.2, 0.2, 0.2));
 
-        AxisAlignedBox worldBounds = new AxisAlignedBox(new Vector3(-150, -150, -150),
-                                                        new Vector3(150, 150, 150));
+        Entity inf = system.addEntity();
+        inf.add(DirectionLight.ID).getData().setColor(new ColorRGB(1, 1, 1))
+           .setShadowCaster(true);
+        inf.add(Transform.ID)
+           .getData()
+           .setMatrix(new Matrix4().lookAt(new Vector3(), new Vector3(.3 * BOUNDS,
+                                                                      .3 * BOUNDS,
+                                                                      .3 * BOUNDS),
+                                           new Vector3(0, 1, 0)));
+
+        AxisAlignedBox worldBounds = new AxisAlignedBox(new Vector3(-1.5 * BOUNDS / 2,
+                                                                    -1.5 * BOUNDS / 2,
+                                                                    -1.5 * BOUNDS / 2),
+                                                        new Vector3(1.5 * BOUNDS / 2,
+                                                                    1.5 * BOUNDS / 2,
+                                                                    1.5 * BOUNDS / 2));
         Controller animator = new AnimationController();
         Controller boundsUpdate = new WorldBoundsController();
         Controller frustumUpdate = new CameraController();
+        Controller smUpdate = new ShadowFrustumController();
         Controller indexBuilder = new SpatialIndexController(new QuadTree<Entity>(worldBounds,
                                                                                   6));
         Controller pvsComputer = new VisibilityController();
         Map<String, Controller> controllers = new HashMap<String, Controller>();
         controllers.put("anim", animator);
         controllers.put("bounds", boundsUpdate);
+        controllers.put("shadow", smUpdate);
         controllers.put("frustum", frustumUpdate);
         controllers.put("index-build", indexBuilder);
         controllers.put("pvs", pvsComputer);
         system.getControllerManager().addController(animator);
         system.getControllerManager().addController(boundsUpdate);
         system.getControllerManager().addController(frustumUpdate);
+        system.getControllerManager().addController(smUpdate);
         system.getControllerManager().addController(indexBuilder);
         system.getControllerManager().addController(pvsComputer);
         system.getControllerManager().addController(lights);

File pom.xml

View file
 	</scm>
 
 	<properties>
-		<entreri.version>1.5.3</entreri.version>
+		<entreri.version>1.6.0-SNAPSHOT</entreri.version>
 	</properties>
 
 	<profiles>