/* * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ package javax.media.j3d; import javax.vecmath.Point3f; /** * A Retained PointLight source. */ class PointLightRetained extends LightRetained { static final int POSITION_CHANGED = LAST_DEFINED_BIT << 1; static final int ATTENUATION_CHANGED = LAST_DEFINED_BIT << 2; static final int LAST_POINTLIGHT_DEFINED_BIT = ATTENUATION_CHANGED; /** * The attenuation vector consisting of * constant, linear, and quadratic coefficients. */ Point3f attenuation = new Point3f(1.0f, 0.0f, 0.0f); // The position at which this light source exists. Point3f position = new Point3f(); // The transformed position of this light Point3f xformPosition = new Point3f(); // local to vworld scale for attenuation double localToVworldScale; // scaled linearAttenuation from lc to ec float linearAttenuationInEc; // scaled quadraticAttenuation from lc to ec float quadraticAttenuationInEc; PointLightRetained() { this.nodeType = NodeRetained.POINTLIGHT; lightType = 3; localBounds = new BoundingBox((Bounds)null); } /** * Initializes this light's position from the vector provided. * @param position the new position */ void initPosition(Point3f position) { this.position.set(position); if (staticTransform != null) { staticTransform.transform.transform(this.position, this.position); } } /** * Sets this light's position from the vector provided. * @param position the new position */ void setPosition(Point3f position) { initPosition(position); sendMessage(POSITION_CHANGED, new Point3f(position)); } /** * Initializes this light's position from the three values provided. * @param x the new x position * @param y the new y position * @param z the new z position */ void initPosition(float x, float y, float z) { this.position.x = x; this.position.y = y; this.position.z = z; if (staticTransform != null) { staticTransform.transform.transform(this.position, this.position); } } /** * Sets this light's position from the three values provided. * @param x the new x position * @param y the new y position * @param z the new z position */ void setPosition(float x, float y, float z) { setPosition(new Point3f(x, y, z)); } /** * Retrieves this light's position and places it in the * vector provided. * @param position the variable to receive the position vector */ void getPosition(Point3f position) { position.set(this.position); if (staticTransform != null) { Transform3D invTransform = staticTransform.getInvTransform(); invTransform.transform(position, position); } } /** * Initializes the point light's attenuation constants. * @param attenuation a vector consisting of constant, linear, and quadratic coefficients */ void initAttenuation(Point3f attenuation) { this.attenuation.set(attenuation); } /** * Sets the point light's attenuation constants. * @param attenuation a vector consisting of constant, linear, and quadratic coefficients */ void setAttenuation(Point3f attenuation) { initAttenuation(attenuation); sendMessage(ATTENUATION_CHANGED, new Point3f(attenuation)); } /** * Sets the point light's attenuation. * @param constant the point light's constant attenuation * @param linear the linear attenuation of the light * @param quadratic the quadratic attenuation of the light */ void initAttenuation(float constant, float linear, float quadratic) { this.attenuation.x = constant; this.attenuation.y = linear; this.attenuation.z = quadratic; } /** * Sets the point light's attenuation. * @param constant the point light's constant attenuation * @param linear the linear attenuation of the light * @param quadratic the quadratic attenuation of the light */ void setAttenuation(float constant, float linear, float quadratic) { setAttenuation(new Point3f(constant, linear, quadratic)); } /** * Retrieves the light's attenuation and places the value in the parameter * specified. * @param attenuation the variable that will contain the attenuation */ void getAttenuation(Point3f attenuation) { attenuation.set(this.attenuation); } /** * This update function, and its native counterpart, * updates a point light. This includes its color, attenuation, * and its transformed position. */ @Override void update(Context ctx, int lightSlot, double scale) { validateAttenuationInEc(scale); Pipeline.getPipeline().updatePointLight(ctx, lightSlot, color.x, color.y, color.z, attenuation.x, linearAttenuationInEc, quadraticAttenuationInEc, xformPosition.x, xformPosition.y, xformPosition.z); } @Override void setLive(SetLiveState s) { super.setLive(s); J3dMessage createMessage = super.initMessage(9); Object[] objs = (Object[])createMessage.args[4]; objs[7] = new Point3f(position); objs[8] = new Point3f(attenuation); VirtualUniverse.mc.processMessage(createMessage); } // This is called only from SpotLightRetained, so as // to not create a message for initialization. for spotlight // the initialization of the message is done by SpotLightRetained @Override void doSetLive(SetLiveState s) { super.setLive(s); } @Override J3dMessage initMessage(int num) { J3dMessage createMessage = super.initMessage(num); Object[] objs = (Object[])createMessage.args[4]; objs[7] = new Point3f(position); objs[8] = new Point3f(attenuation); return createMessage; } // Note : if you add any more fields here , you need to update // updateLight() in RenderingEnvironmentStructure @Override void updateMirrorObject(Object[] objs) { int component = ((Integer)objs[1]).intValue(); Transform3D mlLastLocalToVworld; int i; int numLgts = ((Integer)objs[2]).intValue(); LightRetained[] mLgts = (LightRetained[]) objs[3]; if ((component & POSITION_CHANGED) != 0) { for (i = 0; i < numLgts; i++) { if (mLgts[i] instanceof PointLightRetained) { PointLightRetained ml = (PointLightRetained)mLgts[i]; mlLastLocalToVworld = ml.getLastLocalToVworld(); ml.position = (Point3f) objs[4]; mlLastLocalToVworld.transform(ml.position, ml.xformPosition); ml.localToVworldScale = mlLastLocalToVworld.getDistanceScale(); } } } else if ((component & ATTENUATION_CHANGED) != 0) { for (i = 0; i < numLgts; i++) { if (mLgts[i] instanceof PointLightRetained) { PointLightRetained ml = (PointLightRetained)mLgts[i]; ml.attenuation.set((Point3f)objs[4]); } } } else if ((component & INIT_MIRROR) != 0) { for (i = 0; i < numLgts; i++) { if (mLgts[i] instanceof PointLightRetained) { PointLightRetained ml = (PointLightRetained)mirrorLights[i]; ml.position = (Point3f)((Object[]) objs[4])[7]; ml.attenuation.set((Point3f)((Object[]) objs[4])[8]); mlLastLocalToVworld = ml.getLastLocalToVworld(); mlLastLocalToVworld.transform(ml.position, ml.xformPosition); ml.localToVworldScale = mlLastLocalToVworld.getDistanceScale(); } } } // call the parent's mirror object update routine super.updateMirrorObject(objs); } void validateAttenuationInEc(double vworldToCoexistenceScale) { double localToEcScale = localToVworldScale * vworldToCoexistenceScale; linearAttenuationInEc = (float)(attenuation.y / localToEcScale); quadraticAttenuationInEc = (float)(attenuation.z / (localToEcScale * localToEcScale)); } // Clones only the retained side, internal use only @Override protected Object clone() { PointLightRetained pr = (PointLightRetained)super.clone(); pr.attenuation = new Point3f(attenuation); pr.position = new Point3f(position); pr.xformPosition = new Point3f(); return pr; } // Called on the mirror object @Override void updateTransformChange() { super.updateTransformChange(); Transform3D lastLocalToVworld = getLastLocalToVworld(); lastLocalToVworld.transform(position, xformPosition); localToVworldScale = lastLocalToVworld.getDistanceScale(); validateAttenuationInEc(0.0861328125); } @Override void sendMessage(int attrMask, Object attr) { J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.LIGHT_CHANGED; createMessage.args[0] = this; createMessage.args[1]= new Integer(attrMask); if (inSharedGroup) createMessage.args[2] = new Integer(numMirrorLights); else createMessage.args[2] = new Integer(1); createMessage.args[3] = mirrorLights.clone(); createMessage.args[4] = attr; VirtualUniverse.mc.processMessage(createMessage); } @Override void mergeTransform(TransformGroupRetained xform) { super.mergeTransform(xform); xform.transform.transform(position, position); } }