package min3d.vos; import java.nio.FloatBuffer; import min3d.Utils; import min3d.interfaces.IDirtyParent; /** * Consists of three main components - ambient color, diffuse color, and position. * * Must be added to Scene to take effect. * Eg, "scene.lights().add(myLight);" * * WARNING: Positional light type does not work in v1.5 emulator. * But is nevertheless the default type. */ public class Light extends AbstractDirtyManaged implements IDirtyParent { private BooleanManaged _isVisible; public Number3dManaged position; public Number3dManaged direction; public Color4Managed ambient; public Color4Managed diffuse; public Color4Managed specular; public Color4Managed emissive; private LightType _type; private Number3dManaged _attenuation; // (using the 3 properties of N3D for the 3 attenuation properties) private FloatBuffer _positionAndTypeFloatBuffer; public Light() { super(null); ambient = new Color4Managed(128,128,128, 255, this); diffuse = new Color4Managed(255,255,255, 255, this); specular = new Color4Managed(0,0,0,255, this); emissive = new Color4Managed(0,0,0,255, this); position = new Number3dManaged(0f, 0f, 5f, this); direction = new Number3dManaged(0f, 0f, -1f, this); _attenuation = new Number3dManaged(1f,0f,0f, this); // (OpenGL default attenuation values) _isVisible = new BooleanManaged(true, this); type(LightType.DIRECTIONAL); _positionAndTypeFloatBuffer = Utils.makeFloatBuffer4(0,0,0,0); setDirtyFlag(); } // public boolean isVisible() { return _isVisible.get(); } public void isVisible(Boolean $b) { _isVisible.set($b); } // /** * type can be either POSITIONAL or DIRECTIONAL. * Default is DIRECTIONAL. * * POSITIONAL does not work correctly with v1.5 emulator, which * appears to be a known bug. It does not work corrctly for me * with the v2.2 emulator either. */ public LightType type() { return _type; } public void type(LightType $type) { _type = $type; position.setDirtyFlag(); // .. because position and 'type' go together in OGL data structure } // public float attenuationConstant() { return _attenuation.getX(); } public void attenuationConstant(float $normalizedValue) { _attenuation.setX($normalizedValue); setDirtyFlag(); } public float attenuationLinear() { return _attenuation.getY(); } public void attenuationLinear(float $normalizedValue) { _attenuation.setY($normalizedValue); setDirtyFlag(); } public float attenuationQuadratic() { return _attenuation.getZ(); } public void attenuationQuadratic(float $normalizedValue) { _attenuation.setZ($normalizedValue); setDirtyFlag(); } public void attenuationSetAll(float $constant, float $linear, float $quadratic) { _attenuation.setAll($constant, $linear, $quadratic); setDirtyFlag(); } // public void setAllDirty() { position.setDirtyFlag(); ambient.setDirtyFlag(); diffuse.setDirtyFlag(); specular.setDirtyFlag(); emissive.setDirtyFlag(); direction.setDirtyFlag(); _attenuation.setDirtyFlag(); _isVisible.setDirtyFlag(); } public void onDirty() { setDirtyFlag(); } /** * Used by Renderer */ public Number3dManaged attenuation() { return _attenuation; } /** * Used by Renderer */ public BooleanManaged isVisibleBm() { return _isVisible; } /** * Used by Renderer */ public FloatBuffer positionAndTypeBuffer() { return _positionAndTypeFloatBuffer; } /** * Used by Renderer */ public void commitPositionAndTypeBuffer() { // GL_POSITION takes 4 arguments, the first 3 being x/y/z position, // and the 4th being what we're calling 'type' (positional or directional) _positionAndTypeFloatBuffer.position(0); _positionAndTypeFloatBuffer.put(position.getX()); _positionAndTypeFloatBuffer.put(position.getY()); _positionAndTypeFloatBuffer.put(position.getZ()); _positionAndTypeFloatBuffer.put(_type.glValue()); _positionAndTypeFloatBuffer.position(0); } }