001: /*
002: * $Header: /cvs/j3dfly/J3dFly/src/org/jdesktop/j3dfly/utils/environment/SkyBehavior.java,v 1.1 2005/04/20 21:04:53 paulby Exp $
003: *
004: * Sun Public License Notice
005: *
006: * The contents of this file are subject to the Sun Public License Version
007: * 1.0 (the "License"). You may not use this file except in compliance with
008: * the License. A copy of the License is available at http://www.sun.com/
009: *
010: * The Original Code is Java 3D(tm) Fly Through.
011: * The Initial Developer of the Original Code is Paul Byrne.
012: * Portions created by Paul Byrne are Copyright (C) 2002.
013: * All Rights Reserved.
014: *
015: * Contributor(s): Paul Byrne.
016: *
017: **/
018: package org.jdesktop.j3dfly.utils.environment;
019:
020: import javax.media.j3d.Behavior;
021: import javax.media.j3d.WakeupOnElapsedTime;
022: import javax.media.j3d.BranchGroup;
023: import javax.media.j3d.TransformGroup;
024: import javax.media.j3d.Transform3D;
025: import javax.media.j3d.BoundingSphere;
026: import javax.media.j3d.AmbientLight;
027: import javax.media.j3d.DirectionalLight;
028:
029: import javax.vecmath.Point3d;
030: import javax.vecmath.Vector3f;
031: import javax.vecmath.Color3f;
032:
033: import org.jdesktop.j3dfly.utils.environment.geometry.SkyDome;
034:
035: /**
036: *
037: *
038: * @author paulby
039: * @version
040: */
041: public class SkyBehavior extends Behavior {
042:
043: private SkyDome skyDome;
044: private TransformGroup skyTG;
045: private Transform3D t3d;
046:
047: private WakeupOnElapsedTime timeWakeup = new WakeupOnElapsedTime(50);
048:
049: private float timeOfDay = 5.0f; // 0 - 24
050: private float sunrise = 6f;
051: private float timeStep = 1f / 60f; // Step is 1 minute
052:
053: private float sunsetStart = 18f - timeStep * 5;
054: private float sunsetEnd = 18f + timeStep * 15;
055: private float sunriseStart = 6f - timeStep * 15;
056: private float sunriseEnd = 6f + timeStep * 5;
057:
058: private AmbientLight ambLight;
059: private DirectionalLight sunLight;
060: private DirectionalLight moonLight;
061:
062: private SkyTimeListener listener = null;
063:
064: /** Creates new SkyBehavior */
065: public SkyBehavior(SkyDome skyDome, TransformGroup skyTG,
066: BranchGroup lightBG) {
067: this .skyDome = skyDome;
068: this .skyTG = skyTG;
069:
070: t3d = new Transform3D();
071:
072: setupLights(lightBG);
073:
074: setSchedulingBounds(new BoundingSphere(new Point3d(),
075: Double.POSITIVE_INFINITY));
076: }
077:
078: private void setupLights(BranchGroup lightBG) {
079: BoundingSphere bigBounds = new BoundingSphere(new Point3d(),
080: Double.POSITIVE_INFINITY);
081:
082: ambLight = new AmbientLight();
083: sunLight = new DirectionalLight();
084: moonLight = new DirectionalLight();
085:
086: sunLight.setCapability(DirectionalLight.ALLOW_DIRECTION_WRITE);
087: sunLight.setCapability(DirectionalLight.ALLOW_COLOR_WRITE);
088: sunLight.setDirection(new Vector3f(0f, -1f, 0f));
089: sunLight.setColor(new Color3f(1f, 1f, 168 / 255f));
090:
091: moonLight.setCapability(DirectionalLight.ALLOW_DIRECTION_WRITE);
092: moonLight.setCapability(DirectionalLight.ALLOW_COLOR_WRITE);
093: moonLight.setDirection(new Vector3f(0f, 1f, 0f));
094: moonLight.setColor(new Color3f(232 / 255f, 231 / 255f,
095: 222 / 255f));
096:
097: ambLight.setColor(new Color3f(0.1f, 0.1f, 0.1f));
098:
099: ambLight.setInfluencingBounds(bigBounds);
100: sunLight.setInfluencingBounds(bigBounds);
101: moonLight.setInfluencingBounds(bigBounds);
102:
103: // Putting lights under a changing TransformGroup can cause unnecessary
104: // computation in this example. When a light has infinite bounds it is
105: // better to change the direction of light rather than transform it
106:
107: lightBG.addChild(sunLight);
108: lightBG.addChild(moonLight);
109: lightBG.addChild(ambLight);
110: }
111:
112: private void moveLights(Transform3D skyT3D) {
113: Vector3f v = new Vector3f(0f, -1f, 0f);
114:
115: skyT3D.transform(v);
116: sunLight.setDirection(v);
117:
118: v.x = 0f;
119: v.y = 1f;
120: v.z = 0f;
121: skyT3D.transform(v);
122: moonLight.setDirection(v);
123: }
124:
125: /**
126: * Darken sky - factor 0 is black
127: * factor 1 is daylight
128: */
129: private void setDarkness(float factor) {
130: skyDome.setDarkness(factor);
131:
132: Color3f clr = new Color3f(1f * factor, 1f * factor,
133: 168 / 255f * factor);
134: sunLight.setColor(clr);
135:
136: float moonBrightness = 0.4f;
137:
138: clr.x = 232 / 255f * (1 - factor) * moonBrightness;
139: clr.y = 231 / 255f * (1 - factor) * moonBrightness;
140: clr.z = 222 / 255f * (1 - factor) * moonBrightness;
141:
142: moonLight.setColor(clr);
143: }
144:
145: public void initialize() {
146: wakeupOn(timeWakeup);
147: }
148:
149: public void processStimulus(java.util.Enumeration e) {
150: updateSky();
151:
152: wakeupOn(timeWakeup);
153: }
154:
155: protected void setTimeOfDay(float time) {
156: if ((time > sunsetEnd || time < sunriseStart)
157: && skyDome.getDarkness() != 0f) {
158: skyDome.setDarkness(0f);
159: } else if ((time > sunriseEnd && time < sunsetStart)
160: && skyDome.getDarkness() != 1f) {
161: skyDome.setDarkness(1f);
162: }
163:
164: timeOfDay = time;
165: updateSky();
166: }
167:
168: private void updateSky() {
169: float sunElevation = (float) Math.PI / 12f
170: * (timeOfDay - sunrise);
171:
172: t3d.rotZ(sunElevation - Math.PI / 2);
173:
174: skyTG.setTransform(t3d);
175: moveLights(t3d);
176:
177: //System.out.println(timeOfDay);
178:
179: // Sunset
180: if (timeOfDay >= sunsetStart && timeOfDay <= sunsetEnd) {
181: setDarkness((sunsetEnd - timeOfDay)
182: / (sunsetEnd - sunsetStart));
183: }
184:
185: // Sunrise
186: if (timeOfDay >= sunriseStart && timeOfDay <= sunriseEnd) {
187: setDarkness(1f - ((sunriseEnd - timeOfDay) / (sunriseEnd - sunriseStart)));
188: }
189:
190: if (listener != null)
191: listener.timeOfDayChange(timeOfDay);
192:
193: timeOfDay = (timeOfDay + timeStep) % 24f;
194: }
195:
196: /**
197: * Add a listener for time change events
198: */
199: void addTimeChangeListener(SkyTimeListener listener) {
200: if (this .listener != null)
201: throw new RuntimeException(
202: "Only a single SkyTimeListener is supported");
203: else
204: this.listener = listener;
205: }
206:
207: }
|