001:/*
002: * Copyright (c) 2001 Silvere Martin-Michiellot All Rights Reserved.
003: *
004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
005: * royalty free, license to use, modify and redistribute this
006: * software in source and binary code form,
007: * provided that i) this copyright notice and license appear on all copies of
008: * the software; and ii) Licensee does not utilize the software in a manner
009: * which is disparaging to Silvere Martin-Michiellot.
010: *
011: * This software is provided "AS IS," without a warranty of any kind. ALL
012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
024: *
025: * This software is not designed or intended for use in on-line control of
026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
027: * the design, construction, operation or maintenance of any nuclear
028: * facility. Licensee represents and warrants that it will not use or
029: * redistribute the Software for such purposes.
030: *
031: * @Author: Silvere Martin-Michiellot
032: *
033: */
034:
035:package com.db.server;
036:
037:import java.awt.GraphicsConfigTemplate;
038:import java.awt.GraphicsConfiguration;
039:import java.awt.GraphicsEnvironment;
040:import java.lang.IllegalArgumentException;
041:import java.net.InetAddress;
042:import javax.media.j3d.*;
043:import javax.vecmath.*;
044:import com.sun.j3d.audioengines.javasound.*;
045:import com.sun.j3d.utils.universe.*;
046:
047:import com.db.utils.timers.*;
048:
049:/**
050: * Instancited on the Client, ClientInformation is passed to the server to establish a connection.
051: * It should never leave the server but be destroyed upon disconnection or upon reconnection with the same login and password.
052: * Access to fields and fields modifications is only possible from the client (and therefore by the Avatar).
053: * There is therefore no check about rights access to fields.
054: */
055:
056:public final class ClientInformation extends Object {
057:
058: /**
059: * Client unique ID from server (internal via network channel)
060: * IP (there might be multiple clients on the same physical machine)
061: * Connexion speed (to optimize settings but may be automatically calculated using a round trip of data with the server)
062: * Country of call (to route data faster)
063: * Connected to:
064: * IP
065: * Port
066: * World Spot (this information can be recomputed using the avatar's position and orientation which isunique for a given Universe)
067: * Avatar (including position and orientation)
068: * 3D Drawing radius (so that the server can push objects from the out cache) (may be calculated automatically by the client based on the user's
069: * hardware information)
070: **/
071:
072: public final static int MODEM56K = 56000;
073: public final static int RNIS = 64000;
074: public final static int ADSL = 128000;
075: public final static int CABLE = 256000;
076: public final static int T1 = 1500000;
077: public final static int T3 = 45000000;
078:
079: private final InetAddress clientIP;
080: private final int clientPort;
081: private final String countryOfCall;
082: private final LoginInformation loginInformation;
083: private final InetAddress serverIP;
084: private final int serverPort;
085: //position is the desired arrival position
086: private final Transform3D position;
087: private int connectionSpeed;
088: private float drawingRadius;
089:
090:
091: //meant to be plural information never ends with an s in English
092: private ClientInformation() {
093:
094: throw new IllegalArgumentException("Client information must have a client IP, a client port, a country of call, a server IP, a server port, a login information, a position.");
095:
096: }
097:
098: //clientIP should always be local IP
099: //account will be created if it does not exist
100: //suplemental information can help the server in building a new account (choose your skin...)
101: //Drawing radius set to 1000.0f, and connection speed to MODEM56K
102: public ClientInformation(InetAddress clientIP, int clientPort, String countryOfCall, InetAddress serverIP, int serverPort, LoginInformation loginInformation, Transform3D position) {
103:
104: this .clientIP = clientIP;
105: this .clientPort = clientPort;
106: this .countryOfCall = countryOfCall;
107: this .serverIP = serverIP;
108: this .serverPort = serverPort;
109: this .loginInformation = loginInformation;
110: this .position = position;
111: this .connectionSpeed = ClientInformation.MODEM56K;
112: this .drawingRadius = 1000.0f;
113:
114: }
115:
116: public final InetAddress getClientIP() {
117:
118: return this .clientIP;
119:
120: }
121:
122: public final int getClientPort() {
123:
124: return this .clientPort;
125:
126: }
127:
128: public final String getCountryOfCall() {
129:
130: return this .countryOfCall;
131:
132: }
133:
134: public final InetAddress getServerIP() {
135:
136: return this .serverIP;
137:
138: }
139:
140: public final int getServerPort() {
141:
142: return this .serverPort;
143:
144: }
145:
146: public final LoginInformation getLoginInformation() {
147:
148: return this .loginInformation;
149:
150: }
151:
152: public final Transform3D getPosition() {
153:
154: return this .position;
155:
156: }
157:
158: public final Transform3D setPosition(Transform3D transform3D) {
159:
160: return this .position;
161:
162: }
163:
164: public final int getConnectionSpeed() {
165:
166: return this .connectionSpeed;
167:
168: }
169:
170: public final void setConnectionSpeed(int connectionSpeed) {
171:
172: this .connectionSpeed = connectionSpeed;
173:
174: }
175:
176: //does a roundtrip to get the bitrate of data transfer
177: public final int autoComputeConnectionSpeed() {
178:
179: long startTime;
180: long stopTime;
181: int connection;
182:
183: //code is similar to client network code:
184: //connect to the server sending a request
185: //YYYYYYYYYYYYYYYYY
186: startTime = System.currentTimeMillis();
187: //wait for a reply
188: //YYYYYYYYYYYYY
189: stopTime = System.currentTimeMillis();
190:
191: //build a pessimistic estimation
192: if ((stopTime-startTime) > 2000) {
193: connection = ClientInformation.MODEM56K;
194: } else {
195: if ((stopTime-startTime) > 1500) {
196: connection = ClientInformation.RNIS;
197: } else {
198: if ((stopTime-startTime) > 1000) {
199: connection = ClientInformation.ADSL;
200: } else {
201: if ((stopTime-startTime) > 600) {
202: connection = ClientInformation.CABLE;
203: } else {
204: if ((stopTime-startTime) > 200) {
205: connection = ClientInformation.T1;
206: } else {
207: connection = ClientInformation.T3;
208: }
209: }
210: }
211: }
212: }
213:
214: return connection;
215:
216: }
217:
218: public final float getDrawingRadius() {
219:
220: return this .drawingRadius;
221:
222: }
223:
224: public final void setDrawingRadius(float drawingRadius) {
225:
226: this .drawingRadius = drawingRadius;
227:
228: }
229:
230: //given local time (network traffic), client performance (processor, memory, graphics), prefered places...
231: //compute a drawing radius around the user
232: //this is a very long call, don't do it unless you need it
233: //used to assign viewPlatform
234: public final float autoComputeDrawingRadius() {
235:
236: float proposedDrawingRadius = 1000.0f;
237:
238: Canvas3D canvas3D;
239: JavaSoundMixer javaSoundMixer;
240:
241: float fieldOfView = (float)Math.PI/2;
242: float frontClip = 0.01f;
243: float backClip = 30.0f;
244:
245: GraphicsConfigTemplate3D graphicsConfigTemplate3D;
246: GraphicsConfiguration graphicsConfiguration;
247:
248: VirtualUniverse virtualUniverse;
249: Locale locale;
250: PhysicalBody physicalBody;
251: PhysicalEnvironment physicalEnvironment;
252: boolean volumeMenuEnabled;
253: View view;
254:
255: BranchGroup LightsBranchGroup;
256: BranchGroup BrowserBranchGroup;
257: ViewerAvatar AvatarBranchGroup;
258: PlatformGeometry ConsoleBranchGroup;
259: BranchGroup UserBranchGroup;
260: TransformGroup UserTransform;
261:
262: DirectionalLight headLight;
263: AmbientLight ambientLight;
264:
265: ViewPlatform viewPlatform;
266: float activationRadius;
267:
268: BoundingSphere browserBounds;
269: BoundingSphere lightBounds;
270:
271: long startTime;
272: long stopTime;
273: long frames;
274:
275: graphicsConfigTemplate3D = new GraphicsConfigTemplate3D();
276: graphicsConfigTemplate3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED);
277: graphicsConfigTemplate3D.setDoubleBuffer(GraphicsConfigTemplate.REQUIRED);
278: graphicsConfigTemplate3D.setStereo(GraphicsConfigTemplate.UNNECESSARY);
279: graphicsConfigTemplate3D.setDepthSize(16);
280: graphicsConfigTemplate3D.setRedSize(2);
281: graphicsConfigTemplate3D.setBlueSize(2);
282: graphicsConfigTemplate3D.setGreenSize(2);
283: graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(graphicsConfigTemplate3D);
284:
285: //set up a complex invisible canvas3D
286: virtualUniverse = new VirtualUniverse();
287: locale = new Locale(virtualUniverse);
288: physicalBody = new PhysicalBody();
289: physicalEnvironment = new PhysicalEnvironment();
290: javaSoundMixer = new JavaSoundMixer(physicalEnvironment);
291: volumeMenuEnabled = javaSoundMixer.initialize();
292: fieldOfView = (float)Math.PI/2;
293: frontClip = 0.01f;
294: backClip = 30.0f;
295: canvas3D = new Canvas3D(graphicsConfiguration);
296: view = new View();
297: view.setFieldOfView(fieldOfView);
298: view.setFrontClipDistance(frontClip);
299: view.setBackClipDistance(backClip);
300: view.addCanvas3D(canvas3D);
301: view.setPhysicalBody(physicalBody);
302: view.setPhysicalEnvironment(physicalEnvironment);
303:
304: UserBranchGroup = new BranchGroup();
305: UserBranchGroup.setCapability(Node.ALLOW_BOUNDS_READ);
306: UserBranchGroup.setCapability(Group.ALLOW_CHILDREN_READ);
307: UserBranchGroup.setCapability(Group.ALLOW_CHILDREN_WRITE);
308: UserBranchGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND);
309:
310: UserTransform = new TransformGroup();
311: UserTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
312: UserTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
313: UserTransform.setCapability(Group.ALLOW_CHILDREN_READ);
314: UserTransform.setCapability(Group.ALLOW_CHILDREN_WRITE);
315: UserTransform.setCapability(Group.ALLOW_CHILDREN_EXTEND);
316:
317: UserBranchGroup.addChild(UserTransform);
318:
319: viewPlatform = new ViewPlatform();
320: viewPlatform.setActivationRadius(proposedDrawingRadius);
321:
322: view.attachViewPlatform(viewPlatform);
323: UserTransform.addChild(viewPlatform);
324:
325: LightsBranchGroup = new BranchGroup();
326: LightsBranchGroup.setCapability(Node.ALLOW_BOUNDS_READ);
327: LightsBranchGroup.setCapability(Group.ALLOW_CHILDREN_READ);
328: LightsBranchGroup.setCapability(Group.ALLOW_CHILDREN_WRITE);
329: LightsBranchGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND);
330:
331: lightBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), Double.MAX_VALUE);
332:
333: headLight = new DirectionalLight(true, new Color3f(0.8f, 0.8f, 0.8f), new Vector3f(0.0f, 0.0f, -1.0f));
334: headLight.setCapability(Light.ALLOW_STATE_WRITE);
335: headLight.setInfluencingBounds(lightBounds);
336:
337: LightsBranchGroup.addChild(headLight);
338:
339: ambientLight = new AmbientLight(true, new Color3f(0.2f, 0.2f, 0.2f));
340: ambientLight.setInfluencingBounds(lightBounds);
341: ambientLight.setCapability(Light.ALLOW_STATE_WRITE);
342:
343: LightsBranchGroup.addChild(ambientLight);
344:
345: UserTransform.addChild(LightsBranchGroup);
346:
347: BrowserBranchGroup = new BranchGroup();
348: BrowserBranchGroup.setCapability(Group.ALLOW_CHILDREN_READ);
349: BrowserBranchGroup.setCapability(Group.ALLOW_CHILDREN_WRITE);
350:
351: UserTransform.addChild(BrowserBranchGroup);
352:
353: AvatarBranchGroup = new ViewerAvatar();
354: //Avatar
355: UserTransform.addChild(AvatarBranchGroup);
356:
357: ConsoleBranchGroup = new PlatformGeometry();
358: //Console
359: UserTransform.addChild(ConsoleBranchGroup);
360:
361: LightsBranchGroup.compile();
362: BrowserBranchGroup.compile();
363: AvatarBranchGroup.compile();
364: ConsoleBranchGroup.compile();
365:
366: UserBranchGroup.compile();
367: locale.addBranchGraph(UserBranchGroup);
368:
369: //run for a few frames
370: startTime = System.currentTimeMillis();
371:
372: //do something
373: //YYYYYYYYYYYYYYYYYYYYYy
374:
375: //or something else
376:
377: stopTime = System.currentTimeMillis();
378: frames = view.getFrameNumber();
379: javaSoundMixer.close();
380: view.removeCanvas3D(canvas3D);
381: locale.removeBranchGraph(UserBranchGroup);
382: virtualUniverse.removeAllLocales();
383:
384: return (stopTime-startTime)/frames*3;
385:
386: }
387:
388: File file = new File( tfFileFolder.getText() );
389: Plant plant = new Plant(file, 100, 100);
390: plant.setSelected();
391: m_vPlants.add(plant);
392:
393: /**The speed of how fast the plants shall grow*/
394: public float m_fTimeFactor;
395: /**A list of all plants in this scene*/
396: public Vector m_vPlants;
397: /**A list of all object to be animated of all plants.*/
398: private Vector m_vAnimation;
399:
400: /**Constructor.
401: Creates the whole 3D scene and addt the plants to it. The animation is started
402: immediately when the scene is built.
403: @param vPlants The list of plants to add to the scene
404: @param fTimeFactor The time factor of the growth speed.
405: @exception Throws an exception if received from a caled method.
406: */
407: public void Scene(Vector vPlants, float fTimeFactor)
408: {
409: m_vPlants = vPlants;
410: m_fTimeFactor = fTimeFactor;
411:
412: //create canvas
413: Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
414:
415: //set layout of applet and add canvas
416: setLayout(new BorderLayout());
417: add("Center", canvas);
418:
419: //create view platform
420: ViewPlatform vp = new ViewPlatform();
421: vp.setActivationRadius(1000.0f);
422:
423: PhysicalBody body = new PhysicalBody();
424: PhysicalEnvironment environment = new PhysicalEnvironment();
425:
426: //create new view object and make connections to canvas, view platform, physical body and physical environment
427: View view = new View();
428: view.addCanvas3D(canvas);
429: view.attachViewPlatform(vp);
430: view.setPhysicalBody(body);
431: view.setPhysicalEnvironment(environment);
432: view.setBackClipDistance(1000.0);
433:
434: //set initial position to a new transform group and add the view platform
435: Transform3D t3DView = new Transform3D();
436: t3DView.set(new Vector3f(0.0f, 15.0f, 150.0f));
437: //t3DView.rotY(-Math.PI/4);
438: //t3DView.rotX(-Math.PI/16);
439: TransformGroup tgView = new TransformGroup(t3DView);
440: tgView.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
441: tgView.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
442: tgView.addChild(vp);
443:
444: BoundingSphere bsRange = new BoundingSphere(new Point3d(0.0,0.0,0.0), 1000.0);
445:
446: //create branch group for the view and add the transform group
447: BranchGroup bgView = new BranchGroup();
448: bgView.addChild(tgView);
449:
450:
451: //
452: // create the scene branch
453: //
454:
455: //create transform group for the whole scene
456: TransformGroup tgMouse = new TransformGroup();
457: /*tgMouse.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
458: tgMouse.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
459:
460: //add mouse rotation capability for the scene
461: MouseRotate mr = new MouseRotate(tgMouse);
462: tgMouse.addChild(mr);
463: mr.setSchedulingBounds(bsRange);
464:
465: //add mouse zoom capability for the scene
466: MouseZoom mz = new MouseZoom(tgMouse);
467: tgMouse.addChild(mz);
468: mz.setSchedulingBounds(bsRange);
469:
470: //add mouse translation capability for the scene
471: MouseTranslate mt = new MouseTranslate(tgMouse);
472: tgMouse.addChild(mt);
473: mt.setSchedulingBounds(bsRange);*/ //add this if you want to move the scene with the mouse
474:
475: Appearance appPath = new Appearance();
476: Material mPath = new Material(Constants.COLOR_DARK_BROWN, Constants.COLOR_BLACK, Constants.COLOR_BROWN, Constants.COLOR_BROWN, 10f);
477: appPath.setMaterial( mPath );
478:
479: //create appearance for ground
480: //a texture showing grass has been tested and is making the navigation too slow
481: Appearance appGround = new Appearance();
482: //Material mGround = new Material(Def.COLOR_DARK_GREEN, Def.COLOR_BLACK, Def.COLOR_BLACK, Def.COLOR_BLACK, 1f);
483: //appGround.setMaterial( mGround );
484: TextureBuilder tbGround = new TextureBuilder();
485: Texture tGround = tbGround.buildTexture("grass.jpg");
486: tGround.setMagFilter( Texture.FASTEST );
487: appGround.setTexture( tGround );
488:
489:
490: //create ground
491:
492: float fEdges[] = {-1000.0f, -1000.0f, 0.0f,
493: -1000.0f, 1000.0f, 0.0f,
494: 1000.0f, 1000.0f, 0.0f,
495: 1000.0f, -1000.0f, 0.0f
496: };
497:
498:
499: float fNormals[] = {
500: 0.0f, 1.0f, 0.0f,
501: 0.0f, 1.0f, 0.0f,
502: 0.0f, 1.0f, 0.0f,
503: 0.0f, 1.0f, 0.0f,
504: };
505:
506: QuadArray qaGround = new QuadArray(4, QuadArray.COORDINATES | QuadArray.NORMALS | QuadArray.TEXTURE_COORDINATE_3);
507: qaGround.setCoordinates(0, fEdges);
508: qaGround.setNormals(0, fNormals);
509: qaGround.setTextureCoordinates(0,fEdges);
510: Shape3D s3dGround = new Shape3D(qaGround,appGround);
511: Transform3D t3dGround = new Transform3D();
512: t3dGround.rotX(Math.PI/2);
513: TransformGroup tgGround = new TransformGroup(t3dGround);
514: tgGround.addChild(s3dGround);
515: tgMouse.addChild(tgGround);
516:
517: //create path
518: float fPath[] = { 1000.0f, 0.01f, 110.0f,//1
519: 1000.0f, 0.01f, 90.0f,//2
520: -1000.0f, 0.01f, 70.0f,
521: -1000.0f, 0.01f, 90.0f
522: };
523:
524: QuadArray qaPath = new QuadArray(4, QuadArray.COORDINATES | QuadArray.NORMALS );//| QuadArray.TEXTURE_COORDINATE_3);
525: qaPath.setCoordinates(0, fPath);
526: qaPath.setNormals(0, fNormals);
527: Shape3D s3dPath = new Shape3D(qaPath,appPath);
528: tgMouse.addChild(s3dPath);
529:
530:
531: //make house
532: TransformGroup tgHouse = getHouseTransformGroup(45, 30, 24);
533: Transform3D t3dHouse = new Transform3D();
534: t3dHouse.setTranslation( new Vector3d( 30.0, 0.0, 40.0 ) );
535: tgHouse.setTransform(t3dHouse);
536: tgMouse.addChild(tgHouse);
537:
538: m_vAnimation = new Vector();
539:
540: //sort list of plants
541: Collections.sort( vPlants );
542:
543: //build plants
544: for ( Enumeration enum = vPlants.elements(); enum.hasMoreElements(); )
545: {
546: Plant plant = (Plant) enum.nextElement();
547:
548: TransformGroup tgPlant = plant.build();//appBranch,appLeaf);
549:
550: Transform3D t3dPlant = new Transform3D();
551: t3dPlant.setTranslation( new Vector3d( plant.getX(), 0.0, plant.getY() ) );
552: tgPlant.setTransform( t3dPlant );
553:
554: tgMouse.addChild(tgPlant);
555:
556: m_vAnimation.addAll( plant.getAnimationList() );
557: }
558:
559: //sort animation list
560: Collections.sort(m_vAnimation);
561:
562: //growth behavior
563: GrowthBehavior behavior = new GrowthBehavior( m_vAnimation, fTimeFactor );
564: behavior.setSchedulingBounds(bsRange);
565: tgMouse.addChild(behavior);
566:
567: //create branch group for the scene
568: BranchGroup bgScene = new BranchGroup();
569:
570: // set the background for the scene
571: TextureBuilder tbBack = new TextureBuilder();
572: Background back = new Background( tbBack.buildImage("sky.jpg") );
573: back.setApplicationBounds(bsRange);
574: bgScene.addChild(back);
575:
576: //create light for scene
577: DirectionalLight dl = new DirectionalLight(Constants.COLOR_WHITE, new Vector3f(-1.0f,-1.0f,-1.0f));
578: dl.setInfluencingBounds(bsRange);
579: bgScene.addChild( dl );
580:
581: DirectionalLight dl2 = new DirectionalLight(Constants.COLOR_WHITE, new Vector3f(1.0f,1.0f,-1.0f));
582: dl2.setInfluencingBounds(bsRange);
583: bgScene.addChild( dl2 );
584:
585: //create an ambient light
586: AmbientLight al = new AmbientLight(Constants.COLOR_WHITE);
587: al.setInfluencingBounds(bsRange);
588: bgScene.addChild( al );
589:
590: //create virtual universe
591: VirtualUniverse vu = new VirtualUniverse();
592:
593: //XXXXXXXXXXXXXXXXXXXXXXkeyboard navigation
594: KeyBehavior knb = new KeyBehavior( tgView );
595: knb.setSchedulingBounds(bsRange);
596: bgView.addChild(knb);
597:
598: //add mouse group
599: bgScene.addChild( tgMouse );
600:
601: //compile scene
602: bgScene.compile();
603:
604: bgView.compile();
605:
606: //create locale and add both, view and scene branches
607: Locale locale = new Locale(vu);
608: locale.addBranchGraph(bgScene);
609: locale.addBranchGraph(bgView);
610: }
611:
612: /**
613: Adds a plant to the scene.
614: @param plant The plant to add.
615: */
616: public void addPlant( Plant plant )
617: {
618: m_vPlants.add( plant );
619: }
620:
621: /**
622: Sets the new time factor for the scene.
623: @param fNewFactor The new time factor for the scene.
624: */
625: public void setTimeFactor( float fNewFactor )
626: {
627: m_fTimeFactor = fNewFactor;
628: }
629:
630: /**
631: Gets the time factor of this scene.
632: @return The time factor.
633: */
634: public float getTimeFactor()
635: {
636: return m_fTimeFactor;
637: }
638:
639: /**The TransfromGroup of the house.*/
640: private TransformGroup m_tgHouse;
641:
642: /**
643: Constructor. Builds a house like shpae with the given measures.
644: The roof is 45° going down to the length-side.
645: @param fLength The lenght of one side of the house.
646: @param fWidth The size of the other side of the house.
647: @param fHeight The height of the sidewalls. The roof top will be half of the width higher.
648: */
649: public TransformGroup getHouseTransformGroup( float fLength, float fWidth, float fHeight )
650: {
651: float front_walls[] = { //wall1
652: 0.0f, 0.0f, 0.0f,//1
653: 0.0f, fHeight, 0.0f,//2
654: fLength, fHeight, 0.0f,//3
655: fLength, 0.0f, 0.0f,//4
656: //wall3
657: fLength, 0.0f, fWidth,//5
658: fLength, fHeight, fWidth,//6
659: 0.0f, fHeight, fWidth,//7
660: 0.0f, 0.0f, fWidth//8
661: };
662:
663: float side_walls[] = {
664: fWidth, 0.0f, 0.0f,//1
665: fWidth, fHeight, 0.0f,//2
666: fWidth/2, fHeight+fWidth/2, 0.0f,//3
667: 0.0f, fHeight, 0.0f,//4
668: 0.0f, 0.0f, 0.0f,//5
669:
670: 0.0f, 0.0f, -fLength,//5
671: 0.0f, fHeight, -fLength,//4
672: fWidth/2, fHeight+fWidth/2, -fLength,//3
673: fWidth, fHeight, -fLength,//2
674: fWidth, 0.0f, -fLength//1
675: };
676:
677:
678: float roof1[] = {
679: fLength*1.1f, -fWidth*0.8f, 0.0f,//1
680: fLength*1.1f, 0.0f, 0.0f,//2
681: 0.0f, 0.0f, 0.0f,//3
682: 0.0f, -fWidth*0.8f, 0.0f//4
683: };
684:
685: float roof2[] = {
686: 0.0f, -fWidth*0.8f, 0.0f,//4
687: 0.0f, 0.0f, 0.0f,//3
688: fLength*1.1f, 0.0f, 0.0f,//2
689: fLength*1.1f, -fWidth*0.8f, 0.0f//1
690: };
691:
692: //create appearance for walls
693: Appearance appWalls = new Appearance();
694: TextureBuilder tbWalls = new TextureBuilder();
695: Texture tWalls = tbWalls.buildTexture("bricks.jpg");
696: appWalls.setTexture( tWalls );
697:
698: //create appearance for roof
699: Appearance appRoof = new Appearance();
700: TextureBuilder tbRoof = new TextureBuilder();
701: Texture tRoof = tbRoof.buildTexture("roof.jpg");
702: appRoof.setTexture( tRoof );
703:
704: //modify appearance to make them visible from both sides (else they are only visible from top)
705: PolygonAttributes pa = new PolygonAttributes();
706: pa.setCullFace(PolygonAttributes.CULL_NONE);
707: pa.setBackFaceNormalFlip(true);
708: appRoof.setPolygonAttributes(pa);
709:
710: //create front walls
711: QuadArray qaWalls = new QuadArray(8, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_3);
712: qaWalls.setCoordinates(0, front_walls);
713: qaWalls.setTextureCoordinates(0,front_walls);
714: Shape3D s3dWalls = new Shape3D();
715: s3dWalls.setGeometry( qaWalls );
716: s3dWalls.setAppearance( appWalls );
717:
718: //create side walls
719: GeometryInfo giSide = new GeometryInfo(GeometryInfo.TRIANGLE_FAN_ARRAY);
720: giSide.setCoordinates( side_walls );
721: int[] iArr = {5,5};
722: giSide.setStripCounts( iArr );
723: //giSide.setTextureCoordinates(0,side_walls);
724: Shape3D s3dSide = new Shape3D();
725: //s3dSide.setGeometry( giSide.getGeometryArray() );
726: s3dSide.setAppearance( appWalls );
727: Transform3D t3dSide = new Transform3D();
728: t3dSide.rotY(-Math.PI/2);
729: TransformGroup tgSide = new TransformGroup(t3dSide);
730: tgSide.addChild(s3dSide);
731:
732: //create roof1
733: QuadArray qaRoof1 = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_3);
734: qaRoof1.setCoordinates(0,roof1);
735: qaRoof1.setTextureCoordinates(0,roof1);
736: Shape3D s3dRoof1 = new Shape3D();
737: s3dRoof1.setGeometry( qaRoof1 );
738: s3dRoof1.setAppearance( appRoof );
739: Transform3D t3dRoof1 = new Transform3D();
740: t3dRoof1.rotX(-Math.PI/4);
741: t3dRoof1.setTranslation( new Vector3f( -fLength*0.05f, fHeight+fWidth/2, fWidth/2 ) );
742: TransformGroup tgRoof1 = new TransformGroup( t3dRoof1 );
743: tgRoof1.addChild(s3dRoof1);
744:
745: //create roof2
746: QuadArray qaRoof2 = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_3);
747: qaRoof2.setCoordinates(0,roof2);
748: qaRoof2.setTextureCoordinates(0,roof2);
749: Shape3D s3dRoof2 = new Shape3D();
750: s3dRoof2.setGeometry( qaRoof2 );
751: s3dRoof2.setAppearance( appRoof );
752: Transform3D t3dRoof2 = new Transform3D();
753: t3dRoof2.rotX(Math.PI/4);
754: t3dRoof2.setTranslation( new Vector3f( -fLength*0.05f, fHeight+fWidth/2, fWidth/2 ) );
755: TransformGroup tgRoof2 = new TransformGroup( t3dRoof2 );
756: tgRoof2.addChild(s3dRoof2);
757:
758: //make TransformGroup and add all walls and the roof
759: m_tgHouse = new TransformGroup();
760: m_tgHouse.addChild(s3dWalls);
761: m_tgHouse.addChild(tgSide);
762: m_tgHouse.addChild(tgRoof1);
763: m_tgHouse.addChild(tgRoof2);
764:
765: return m_tgHouse;
766: }
767:}
|