Commits

Michael Ludwig committed 04b5864

Progress more on lighting implementation, and improve state group model flexibility.

  • Participants
  • Parent commits 2c2c872

Comments (0)

Files changed (15)

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

+package com.ferox.scene.controller.ffp;
+
+import com.ferox.math.Const;
+import com.ferox.math.Matrix4;
+import com.ferox.renderer.Renderer.BlendFactor;
+import com.ferox.scene.Light;
+import com.lhkbob.entreri.Component;
+
+public class AppliedEffects {
+    private final boolean shadowedLightingPhase;
+    // FIXME this might need to be a set, since in the main phase, we need
+    // to specify all shadowed lights so that all of them can be disabled.
+    private final Component<? extends Light<?>> shadowLight;
+    
+    private final boolean blendingEnabled;
+    private final BlendFactor destBlend;
+    private final BlendFactor sourceBlend;
+    
+    private final Matrix4 viewMatrix;
+    
+    public AppliedEffects(@Const Matrix4 view) {
+        shadowedLightingPhase = false;
+        shadowLight = null;
+        blendingEnabled = false;
+        destBlend = BlendFactor.ZERO;
+        sourceBlend = BlendFactor.ONE;
+        viewMatrix = view;
+    }
+    
+    public @Const Matrix4 getViewMatrix() {
+        return viewMatrix;
+    }
+    
+    public boolean isShadowBeingRendered() {
+        return shadowedLightingPhase;
+    }
+    
+    public boolean isBlendingEnabled() {
+        return blendingEnabled;
+    }
+    
+    public BlendFactor getSourceBlendFactor() {
+        return sourceBlend;
+    }
+    
+    public BlendFactor getDestinationBlendFactor() { 
+        return destBlend;
+    }
+    
+    public Component<? extends Light<?>> getShadowCaster() {
+        return shadowLight;
+    }
+}

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

+package com.ferox.scene.controller.ffp;
+
+public class ColorGroupFactory {
+    // Index for this will probably be based off of the hashcode for the colors,
+    // but this is also tiered since multiple color sources play a role
+}

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

 import com.ferox.resource.Texture.WrapMode;
 import com.ferox.scene.Camera;
 import com.ferox.scene.controller.PVSResult;
+import com.ferox.scene.controller.light.LightGroupResult;
 import com.ferox.util.Bag;
 import com.lhkbob.entreri.Component;
 import com.lhkbob.entreri.Entity;
     private final int emissiveTextureUnit;
     
     private List<PVSResult> pvs;
+    private LightGroupResult lightGroups;
     
     private final Queue<Future<Void>> previousFrame;
 
         }
     }
     
+    public static long blocktime = 0L;
     @Override
     @SuppressWarnings("unchecked")
     public void process(double dt) {
         // 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 {
                 throw new RuntimeException("Previous frame failed", e);
             }
         }
+        blocktime += (System.nanoTime() - now);
         previousFrame.addAll(thisFrame);
     }
     
     public static long rendertime = 0L;
     private Future<Void> render(final Surface surface, final Frustum view, Bag<Entity> pvs) {
         GeometryGroupFactory geomGroup = new GeometryGroupFactory(getEntitySystem(), view.getViewMatrix());
-        TextureGroupFactory textureGroup = new TextureGroupFactory(getEntitySystem(), diffuseTextureUnit, emissiveTextureUnit, 
-                                                                   geomGroup);
-        LightGroupFactory lightGroup = new LightGroupFactory(textureGroup);
+//        TextureGroupFactory textureGroup = new TextureGroupFactory(getEntitySystem(), diffuseTextureUnit, emissiveTextureUnit, 
+//                                                                   geomGroup);
+        LightGroupFactory lightGroup = new LightGroupFactory(getEntitySystem(), lightGroups, 8, geomGroup);
         
         final StateNode rootNode = new StateNode(lightGroup.newGroup());
         for (Entity e: pvs) {
                 Context ctx = access.setActiveSurface(surface);
                 if (ctx != null) {
                     FixedFunctionRenderer ffp = ctx.getFixedFunctionRenderer();
-                    ffp.clear(true, true, true, new Vector4(0, 0, 0, 1.0), 1f, 0);
+                    // FIXME clear color should be configurable somehow
+                    ffp.clear(true, true, true, new Vector4(0.0, 0.0, 0.0, 1.0), 1f, 0);
                     ffp.setProjectionMatrix(view.getProjectionMatrix());
                     ffp.setModelViewMatrix(view.getViewMatrix());
                     
-                    rootNode.render(ffp);
+                    rootNode.render(ffp, new AppliedEffects(view.getViewMatrix()));
                     
                     ctx.flush();
                 }
     @Override
     public void preProcess(double dt) {
         pvs = new ArrayList<PVSResult>();
+        lightGroups = null;
     }
     
     @Override
     public void report(Result r) {
         if (r instanceof PVSResult) {
             pvs.add((PVSResult) r);
+        } else if (r instanceof LightGroupResult) {
+            lightGroups = (LightGroupResult) r;
         }
     }
 }

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

         public List<StateNode> getNodes() {
             return allNodes;
         }
+
+        @Override
+        public AppliedEffects applyGroupState(FixedFunctionRenderer r, AppliedEffects effects) {
+            return effects;
+        }
+
+        @Override
+        public void unapplyGroupState(FixedFunctionRenderer r, AppliedEffects effects) {
+            // set attributes to null
+            r.setVertices(null);
+            r.setNormals(null);
+            r.setModelViewMatrix(effects.getViewMatrix());
+        }
     }
     
     private class GeometryState implements State {
         }
 
         @Override
-        public boolean applyState(FixedFunctionRenderer r) {
+        public AppliedEffects applyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
             r.setVertices(geometry.vertices);
             r.setNormals(geometry.normals);
             
                 }
             }
             
-            return true;
+            return effects;
         }
 
         @Override
-        public void unapplyState(FixedFunctionRenderer r) {
+        public void unapplyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
             // do nothing
-            // FIXME set null vertices/normals?
         }
     }
     

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

 package com.ferox.scene.controller.ffp;
 
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
+import com.ferox.math.ColorRGB;
+import com.ferox.math.Matrix4;
+import com.ferox.math.Vector3;
 import com.ferox.math.Vector4;
 import com.ferox.renderer.FixedFunctionRenderer;
+import com.ferox.scene.AmbientLight;
+import com.ferox.scene.DirectionLight;
+import com.ferox.scene.Light;
+import com.ferox.scene.PointLight;
+import com.ferox.scene.Renderable;
+import com.ferox.scene.SpotLight;
+import com.ferox.scene.Transform;
+import com.ferox.scene.controller.light.LightGroupResult;
+import com.lhkbob.entreri.Component;
 import com.lhkbob.entreri.Entity;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.property.IntProperty;
 
 public class LightGroupFactory implements StateGroupFactory {
+    private static final Vector4 BLACK = new Vector4(0.0, 0.0, 0.0, 1.0);
+
     private final StateGroupFactory child;
     
-    public LightGroupFactory(StateGroupFactory child) {
+    private final State[][] groups;
+    private final IntProperty groupAssignment;
+    
+    // components for access
+    private final Renderable renderable;
+    
+    public LightGroupFactory(EntitySystem system, LightGroupResult lightGroups, int maxLights, 
+                             StateGroupFactory child) {
         this.child = child;
+        groupAssignment = lightGroups.getAssignmentProperty();
+        groups = new State[lightGroups.getGroupCount()][];
+        renderable = system.createDataInstance(Renderable.ID);
+        
+        // components for access
+        DirectionLight dl = system.createDataInstance(DirectionLight.ID);
+        SpotLight sl = system.createDataInstance(SpotLight.ID);
+        PointLight pl = system.createDataInstance(PointLight.ID);
+        AmbientLight al = system.createDataInstance(AmbientLight.ID);
+        Transform t = system.createDataInstance(Transform.ID);
+        
+        Matrix4 identity = new Matrix4().setIdentity();
+        
+        for (int i = 0; i < groups.length; i++) {
+            Set<Component<? extends Light<?>>> group = lightGroups.getGroup(i);
+            
+            List<LightState> states = new ArrayList<LightState>();
+            List<Component<?>> unassignedAmbientLights = new ArrayList<Component<?>>();
+            
+            LightState currentState = new LightState(maxLights); // always have one state, even if empty
+            states.add(currentState);
+            
+            int index = 0;
+            for (Component<? extends Light<?>> light: group) {
+                Entity e = light.getEntity();
+                GLLight gl = null;
+                
+                if (light.getTypeId() == DirectionLight.ID && e.get(dl)) {
+                    gl = new GLLight();
+                    gl.setDirectionLight(light, dl.getColor(), 
+                                         (e.get(t) ? t.getMatrix() : identity));
+                } else if (light.getTypeId() == SpotLight.ID && e.get(sl)) {
+                    gl = new GLLight();
+                    gl.setSpotLight(light, sl.getColor(), sl.getCutoffAngle(), 
+                                    sl.getFalloffDistance(), (e.get(t) ? t.getMatrix() : identity));
+                } else if (light.getTypeId() == PointLight.ID && e.get(pl)) {
+                    gl = new GLLight();
+                    gl.setPointLight(light, pl.getColor(), pl.getFalloffDistance(), 
+                                     (e.get(t) ? t.getMatrix() : identity));
+                } else if (light.getTypeId() == AmbientLight.ID) {
+                    if (currentState.ambientColor == null) {
+                        // merge ambient light with this state group
+                        e.get(al);
+                        currentState.setAmbientLight(al.getColor());
+                    } else {
+                        // store the ambient light for later
+                        unassignedAmbientLights.add(light);
+                    }
+                }
+                
+                if (gl != null) {
+                    // have a light to store in the current state
+                    if (index >= maxLights) {
+                        // must move on to a new state
+                        currentState = new LightState(maxLights);
+                        states.add(currentState);
+                        index = 0;
+                    }
+                    currentState.setLight(index++, gl);
+                }
+            }
+            
+            // process any ambient lights that need to go into a state group
+            if (!unassignedAmbientLights.isEmpty()) {
+                for (int j = 0; j < states.size() && !unassignedAmbientLights.isEmpty(); j++) {
+                    if (states.get(j).ambientColor == null) {
+                        // this state can take an ambient light color
+                        Component<?> light = unassignedAmbientLights.remove(unassignedAmbientLights.size() - 1);
+                        if (light.getEntity().get(al)) {
+                            states.get(j).setAmbientLight(al.getColor());
+                        }
+                    }
+                }
+                
+                // if there are still ambient lights, we need one state for
+                // each ambient light without any other configuration
+                while(!unassignedAmbientLights.isEmpty()) {
+                    Component<?> light = unassignedAmbientLights.remove(unassignedAmbientLights.size() - 1);
+                    if (light.getEntity().get(al)) {
+                        LightState state = new LightState(0);
+                        state.setAmbientLight(al.getColor());
+                        states.add(state);
+                    }
+                }
+            }
+            
+            groups[i] = states.toArray(new LightState[states.size()]);
+        }
+    }
+    
+    private static Vector4 convertColor(ColorRGB color) {
+        return new Vector4(color.redHDR(), color.greenHDR(), color.blueHDR(), 1.0);
     }
     
     @Override
     public StateGroup newGroup() {
         return new LightGroup();
     }
-    // The index for LightGroupFactory state is based on the assigned light group,
-    // so the LightGroupFactory instance will know about all possible groups and can do
-    // a simple lookup to which state to use.
     
     private class LightGroup implements StateGroup {
-        private final List<StateNode> singleNode;
+        private final List<StateNode> nodes;
         
         public LightGroup() {
-            singleNode = Arrays.asList(new StateNode((child == null ? null : child.newGroup()), new LightState()));
+            nodes = new ArrayList<StateNode>();
+            for (int i = 0; i < groups.length; i++) {
+                nodes.add(new StateNode((child == null ? null : child.newGroup()), groups[i]));
+            }
         }
         
         @Override
         public StateNode getNode(Entity e) {
-            return singleNode.get(0);
+            if (e.get(renderable)) {
+                int group = groupAssignment.get(renderable.getIndex(), 0);
+                return nodes.get(group);
+            } else {
+                // shouldn't happen
+                return null;
+            }
         }
 
         @Override
         public List<StateNode> getNodes() {
-            return singleNode;
+            return nodes;
+        }
+
+        @Override
+        public AppliedEffects applyGroupState(FixedFunctionRenderer r, AppliedEffects effects) {
+            r.setLightingEnabled(true);
+            return effects;
+        }
+
+        @Override
+        public void unapplyGroupState(FixedFunctionRenderer r, AppliedEffects effects) {
+            r.setLightingEnabled(false);
         }
     }
     
     private class LightState implements State {
+        private Vector4 ambientColor;
+        
+        private final GLLight[] lights;
+        
+        public LightState(int maxLights) {
+            ambientColor = null;
+            lights = new GLLight[maxLights];
+        }
+        
+        public void setAmbientLight(ColorRGB color) {
+            ambientColor = convertColor(color);
+        }
+        
+        public void setLight(int light, GLLight glLight) {
+            lights[light] = glLight;
+        }
+        
         @Override
         public void add(Entity e) {
             // do nothing
         }
 
         @Override
-        public boolean applyState(FixedFunctionRenderer r) {
-            r.setLightingEnabled(true);
-            r.setLightEnabled(0, true);
-            r.setLightPosition(0, new Vector4(1.0, 1.0, 1.0, 1.0));
-            r.setLightColor(0, new Vector4(0.1, 0.1, 0.1, 1.0), new Vector4(.3, .3, .3, 1.0), new Vector4(0, 0, 0, 1));
-            r.setMaterial(new Vector4(0.5, 0.5, 0.5, 1.0), new Vector4(.4, .2, .1, 1.0), new Vector4(.4, .4, .4, 1.0), new Vector4(0, 0, 0, 0));
-            return true;
+        public AppliedEffects applyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
+            if (index > 0) {
+                // FIXME configure additive blending
+            } // FIXME if index == 0 and doing transparent shadows, also do blending?
+            
+            int numLights = 0;
+            
+            if (!effects.isShadowBeingRendered() && ambientColor != null) {
+                // use the defined ambient color during the main render stage,
+                // but not when we're being accumulated for the shadow stage
+                r.setGlobalAmbientLight(ambientColor);
+                numLights++;
+            } else {
+                r.setGlobalAmbientLight(BLACK);
+            }
+            
+            GLLight light;
+            for (int i = 0; i < lights.length; i++) {
+                light = lights[i];
+                
+                if (light != null) {
+                    // check to see if this light should be used for the current
+                    // stage of shadow mapping
+                    if ((effects.isShadowBeingRendered() && light.source == effects.getShadowCaster())
+                        || (!effects.isShadowBeingRendered() && light.source != effects.getShadowCaster())) {
+                        // enable and configure the light
+                        r.setLightEnabled(i, true);
+                        r.setLightPosition(i, light.position);
+                        r.setLightColor(i, BLACK, light.color, light.color);
+
+                        if (light.spotlightDirection != null) {
+                            // configure additional spotlight parameters
+                            // FIXME: remove cast after renderer update
+                            r.setSpotlight(i, light.spotlightDirection, (float) light.cutoffAngle);
+                            if (light.falloff >= 0) {
+                                r.setLightAttenuation(i, 1.0f, 0.0f, (float) (1.0 / (light.falloff * light.falloff)));
+                            } else {
+                                // disable attenuation
+                                r.setLightAttenuation(i, 1.0f, 0.0f, 0.0f);
+                            }
+                        }
+
+                        numLights++;
+                    } else {
+                        // disable the light
+                        r.setLightEnabled(i, false);
+                    }
+                } else {
+                    // disable the light
+                    r.setLightEnabled(i, false);
+                }
+            }
+            
+            // if there aren't any configured lights, no need to render
+            // everything
+            return (numLights > 0 || !effects.isShadowBeingRendered() ? effects : null);
         }
 
         @Override
-        public void unapplyState(FixedFunctionRenderer r) {
-            r.setLightingEnabled(false);
+        public void unapplyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
+            if (index > 0) {
+                // FIXME revert changes to blending
+            }
+        }
+    }
+    
+    private static class GLLight {
+        Vector4 color;
+        Vector4 position;
+        Vector3 spotlightDirection;
+        double cutoffAngle;
+        double falloff;
+        
+        Component<? extends Light<?>> source;
+        
+        public void setDirectionLight(Component<? extends Light<?>> light, ColorRGB color, Matrix4 transform) {
+            position = new Vector4(-transform.m02, -transform.m12, -transform.m22, 0.0);
+            this.color = convertColor(color);
+            spotlightDirection = null;
+            source = light;
+        }
+        
+        public void setSpotLight(Component<? extends Light<?>> light, ColorRGB color, double cutoffAngle, double falloff, Matrix4 transform) {
+            position = new Vector4(transform.m03, transform.m13, transform.m23, 1.0);
+            this.color = convertColor(color);
+            spotlightDirection = new Vector3(transform.m02, transform.m12, transform.m22);
+            this.cutoffAngle = cutoffAngle;
+            this.falloff = falloff;
+            source = light;
+        }
+        
+        public void setPointLight(Component<? extends Light<?>> light, ColorRGB color, double falloff, Matrix4 transform) {
+            position = new Vector4(transform.m03, transform.m13, transform.m23, 1.0);
+            this.color = convertColor(color);
+            spotlightDirection = new Vector3(0.0, 0.0, 1.0); // any non-null direction is fine
+            this.cutoffAngle = 180.0;
+            this.falloff = falloff;
+            source = light;
         }
     }
 }

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

+package com.ferox.scene.controller.ffp;
+
+public class LightingGroupFactory {
+    // FIXME necessary?
+}

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

-package com.ferox.scene.controller.ffp;
-
-public class Materials {
-    // Index for this will probably be based off of the hashcode for the colors,
-    // but this is also tiered since multiple color sources play a role
-}

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

+package com.ferox.scene.controller.ffp;
+
+public class ShadowMapGroupFactory {
+    // I don't think this even has an index, since there is only one group
+    // and it just creates a bunch of states. Only one gropu is needed because
+    // this will be underneath the 'lit' state that enables lighting in general
+}

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

-package com.ferox.scene.controller.ffp;
-
-public class ShadowMapping {
-    // I don't think this even has an index, since there is only one group
-    // and it just creates a bunch of states. Only one gropu is needed because
-    // this will be underneath the 'lit' state that enables lighting in general
-}

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

 public interface State {
     public void add(Entity e);
     
-    public boolean applyState(FixedFunctionRenderer r);
+    public AppliedEffects applyState(FixedFunctionRenderer r, AppliedEffects effects, int index);
     
-    public void unapplyState(FixedFunctionRenderer r);
+    public void unapplyState(FixedFunctionRenderer r, AppliedEffects effects, int index);
 }

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

 
 import java.util.List;
 
+import com.ferox.renderer.FixedFunctionRenderer;
 import com.lhkbob.entreri.Entity;
 
 public interface StateGroup {
     public StateNode getNode(Entity e);
     
     public List<StateNode> getNodes();
+    
+    public AppliedEffects applyGroupState(FixedFunctionRenderer r, AppliedEffects effects);
+    
+    public void unapplyGroupState(FixedFunctionRenderer r, AppliedEffects effects);
 }

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

 
 public class StateNode {
     // for low-level reasons a single high-level state
-    // might be represented as multiple actual state groups
+    // might be represented as multiple actual states
     private final State[] state;
     
     private final StateGroup children;
         }
     }
     
-    public void render(FixedFunctionRenderer r) {
+    public void render(FixedFunctionRenderer r, AppliedEffects effects) {
         List<StateNode> childNodes = (children != null ? children.getNodes() : null);
         int childCount = (children != null ? childNodes.size() : 0);
         
-        for (int i = 0; i < state.length; i++) {
-            if (state[i].applyState(r)) {
-                for (int j = 0; j < childCount; j++) {
-                    childNodes.get(j).render(r);
+        // FIXME we're applying a child group state before the specific states
+        // of this node, which means they can mutate the applied effects too soon,
+        // maybe the StateGroup mutations don't get to mutate the effects?
+        AppliedEffects forStates = (children != null ? children.applyGroupState(r, effects) : effects);
+        if (forStates != null) {
+            for (int i = 0; i < state.length; i++) {
+                AppliedEffects childEffects = state[i].applyState(r, forStates, i);
+                if (childEffects != null) {
+                    for (int j = 0; j < childCount; j++) {
+                        childNodes.get(j).render(r, childEffects);
+                    }
+                    state[i].unapplyState(r, forStates, i);
                 }
-                state[i].unapplyState(r);
+            }
+            
+            if (children != null) {
+                children.unapplyGroupState(r, effects);
             }
         }
     }
         }
 
         @Override
-        public boolean applyState(FixedFunctionRenderer r) {
+        public AppliedEffects applyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
             // do nothing, but continue
-            return true;
+            return effects;
         }
 
         @Override
-        public void unapplyState(FixedFunctionRenderer r) {
+        public void unapplyState(FixedFunctionRenderer r, AppliedEffects effects, int index) {
             // do nothing
         }
     }

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

                 // haven't seen this texture configuration before
                 StateGroup child = (childFactory != null ? childFactory.newGroup() : null);
                 if (diffuseUnit != emissiveUnit || !diffuse.isEnabled() || !emissive.isEnabled()) {
-                    // we have enough units to use a single state
-                    TextureState state = new TextureState(diffuse, emissive);
+                    // we have enough units to use a single state, or only 
+                    // one texture is enabled
+                    TextureState state = new TextureState(new TextureSet(diffuse, emissive));
                     node = new StateNode(child, state);
                     allNodes.add(node);
                     index.put(state.textures, node);
                 } else {
                     // we only have 1 unit available, but both diffuse and emissive
                     // are enabled.
-                    // - the key set is still treated as a single state, though
+                    // - 
                     TextureSet key = new TextureSet(diffuse, emissive);
-                    node = new StateNode(child, new TextureState(diffuse, null), 
-                                         new TextureState(null, emissive));
+                    node = new StateNode(child, new TextureState(key), 
+                                         new TextureState(key));
                     allNodes.add(node);
                     index.put(key, node);
                 }
     private class TextureState implements State {
         private final TextureSet textures; // immutable, don't call set()
         
-        public TextureState(DiffuseColorMap diffuse, EmittedColorMap emissive) {
-            textures = new TextureSet(diffuse, emissive);
+        public TextureState(TextureSet textures) {
+            this.textures = textures;
         }
         
         @Override
 
         @Override
         public boolean applyState(FixedFunctionRenderer r) {
+            
+            
+            
             // FIXME if this is the 2nd state, we need to turn additive blending
             // for the emissive texture instead of using the texture environment
             if (textures.diffuse != null) {
         }
     }
     
+    private static class TextureConfiguration {
+        private Texture texture;
+        private VertexAttribute coords;
+        
+        private Env
+    }
+    
     private static class TextureSet {
         private Texture diffuse;
         private Texture emissive;

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

-package com.ferox.scene.controller.ffp;
-
-public class Transparency {
-    // The index lookup for this is just a boolean, since the
-    // alpha value is assigned by the material state
-}

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

+package com.ferox.scene.controller.ffp;
+
+public class TransparentGroupFactory {
+    // The index lookup for this is just a boolean, since the
+    // alpha value is assigned by the material state
+}