cyan yellOW MagenTa BlacK PanTOne 123 c eMPOWeRIng PRODUcTIVITy FOR The JaVa™ DeVelOPeR The eXPeRT’s VOIce® In JaVa™ TechnOlOgy Companion eBook Available Pro Java™ 6 3D Game Development: IInncclluuddeess J P JJaavvaa™™ SSEE 66 Java 3D,™ JOGL, JInput, and JOAL APIs a PPllaattffoorrmm r v a o Pro Dear Reader, 3 Throw away your keyboard and mouse, and explore strange new lands filled J D with mysterious objects (cows frozen in blocks of ice, chirping penguins, gold- a en globes with wavering eyes), armed with a gamepad, a power glove, or just ,™ Java 6 3D your bare hands. v J The unconventionally In this book, I show you how to develop and program 3D games in Java™ O a ™ handsome author of technology on a PC, with an emphasis on the construction of 3D landscapes. I Killer Game Programming G ™ assume you have a reasonable knowledge of Java, the sort of things picked up in Java L in a first Java course at school. , 6 Different from other Java games programming books, here you’ll find the J focus is on the latest 3D APIs, covering a range of libraries that you can’t find Game Development I 3 described in one place anywhere else. n I’ve split the topics into three sections: Java 3D™ API, nonstandard input p D devices for game playing, and JOGL. Java 3D is a high-level 3D graphics API, u and JOGL is a lower-level Java wrapper around the popular OpenGL graphics t API. I look at three nonstandard input devices: the webcam, the gamepad, and , G the P5 data glove. Along the way, I utilize several other games-related libraries, a a including JInput, JOAL, JMF, and Odejava. I describe the latest Java SE 6 features n Java 3D,™ JOGL, JInput, and JOAL APIs relevant to gaming, including splash screens, JavaScript™ scripting, and the d m desktop and system tray interfaces. J Read, enjoy, and create—new techniques and endless possibilities await, O e using Java 6 for your 3D games programming. A Regards, L D Andrew Davison A e Learn the key techniques needed to create fun, exciting P v I 3D games in Java™ technology, with an emphasis on s e 3D landscape construction THE APRESS JAVA™ ROADMAP l Companion eBook o Beginning Java™ Objects, Java™ 6 p Second Edition Platform Revealed Pro Java™ 6 3D m Game Development Beginning Java™ SE 6 See last page for details on $10 eBook version e n t : Andrew Davison SOURCE CODE ONLINE ISBN-13: 978-1-59059-817-7 ISBN-10: 1-59059-817-2 www.apress.com 59000 java.apress.com Davison http://fivedots.coe.psu.ac.th/~ad/jg2/ Shelve in Java/Games Programming User level: Intermediate–Advanced 9 781590 598177 this print for content only—size & color not accurate 7" x 9-1/4" / CASEBOUND / MALLOY (1.0625 INCH BULK -- 528 pages -- 50# Thor) 817-2FM.qxd 3/27/07 3:40 PM Page i Pro Java 6 3D Game ™ Development Java 3D™, JOGL, JInput, and JOAL APIs Andrew Davison 817-2FM.qxd 3/27/07 3:40 PM Page ii Pro Java™6 3D Game Development: Java 3D™,JOGL,JInput,and JOAL APIs Copyright © 2007 by Andrew Davison All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN-13: 978-1-59059-817-7 ISBN-10: 1-59059-817-2 Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1 Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Apress Inc. is not affiliated with Sun Microsystems, Inc. and this book was written without endorsement from Sun Microsystems, Inc. Lead Editor: Steve Anglin Technical Reviewers: Chien Yang and Shawn Kendall Editorial Board: Steve Anglin, Ewan Buckingham, Gary Cornell, Jason Gilmore, Jonathan Gennick, Jonathan Hassell, Chris Mills, Matthew Moodie, Jeffrey Pepper, Paul Sarknas, Dominic Shakeshaft, JimSumser, Matt Wade Project Manager: Denise Santoro Lincoln Copy Edit Manager: Nicole Flores Copy Editor: Jennifer Whipple Assistant Production Director: Kari Brooks-Copony Senior Production Editor: Laura Cheu Compositor: Gina Rexrode Proofreader: Elizabeth Berry Indexer: Becky Hornyak Artist: Andrew Davison, April Milne Cover Designer: Kurt Krames Manufacturing Director: Tom Debolski Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail [email protected], or visit http://www.springeronline.com. For information on translations, please contact Apress directly at 2560 Ninth Street, Suite 219, Berkeley, CA 94710. Phone 510-549-5930, fax 510-549-5939, e-mail [email protected], or visit http://www.apress.com. The information in this book is distributed on an “as is” basis, without warranty. Although every precau- tion has been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in this work. The source code for this book is available to readers at http://www.apress.comin the Source Code/ Download section. It is also available at the author’s web site at http://fivedots.coe.psu.ac.th/~ad/jg2/. 817-2FM.qxd 3/27/07 3:40 PM Page iii To Supatra and John 817-2FM.qxd 3/27/07 3:40 PM Page iv 817-2FM.qxd 3/27/07 3:40 PM Page v Contents at a Glance About the Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix About the Technical Reviewers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv PART 1 n n nJava 3D nCHAPTER 1 Introducing Java 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 nCHAPTER 2 Get a Life (in 3D). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 nCHAPTER 3 Get a Life (the Java 6 Way) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 nCHAPTER 4 The Colliding Grabbers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 nCHAPTER 5 When Worlds Collide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 nCHAPTER 6 A Multitextured Landscape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 nCHAPTER 7 Walking Around the Models. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 nCHAPTER 8 More Backgrounds and Overlays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 PART 2 n n nNonstandard Input Devices nCHAPTER 9 Webcam Snaps. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 nCHAPTER 10 Navigating a 3D Scene by Waving Your Arm . . . . . . . . . . . . . . . . . . . . . . . . 251 nCHAPTER 11 Building a Gamepad Controller with JInput . . . . . . . . . . . . . . . . . . . . . . . . . 273 nCHAPTER 12 Gamepad Grabbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 nCHAPTER 13 3D Sound with JOAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 nCHAPTER 14 The P5 Glove . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 PART 3 n n nJOGL nCHAPTER 15 Two JOGL Programming Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 nCHAPTER 16 Touring the World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 nCHAPTER 17 Loading Models. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 nINDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 v 817-2FM.qxd 3/27/07 3:40 PM Page vi 817-2FM.qxd 3/27/07 3:40 PM Page vii Contents About the Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix About the Technical Reviewers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv PART 1 n n nJava 3D nCHAPTER 1 Introducing Java 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Overview of Java 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Overview of the Scene Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Some Java 3D Scene Graph Nodes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 The HelloUniverse Scene Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Java 3D Strengths. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 The Scene Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Performance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Unique Features. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Java Integration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Documentation and Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Criticisms of Java 3D for Games Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Java 3D’s Level of Abstraction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Java 3D Games . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Java 3D Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Alternatives to Java 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 nCHAPTER 2 Get a Life (in 3D). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 The Game of Life. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Running Life3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Configuring Life3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 A Life3D Screensaver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 An Overview of the Life3D Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Deciding How to Start. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 vii 817-2FM.qxd 3/27/07 3:40 PM Page viii viii nCONTENTS Displaying the 3D Game. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Integrating Java 3D and Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Window Sizing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Processing Key Presses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Scene Graph Creation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Lighting the Scene. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 The Scene’s Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Building the Cells Grid and Making It Behave. . . . . . . . . . . . . . . . . . . . . . . . 25 Viewer Positioning. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Viewer Movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Behaviors in Java 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 A Time-Based Behavior. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Managing the Grid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Accessing Properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Creating the Grid Scene Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Updating the Cells States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Will the Cell Live or Die?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Rotating the Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 The Cell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Building the Cell’s Scene Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Coloring the Cells. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Setting the Cell’s Visibility. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Changing a Cell’s Life State. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Visual Changes to a Cell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Time for Screensavers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Changing Life3D into a Screensaver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Problems with Screensavers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 The SaverBeans SDK. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 More Life Required? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 nCHAPTER 3 Get a Life (the Java 6 Way). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Life3D Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 An Overview of the Life3D Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Making a Splash. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Animating a Clock. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Drawing onto a Splash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Drawing the Clocks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 JAR Packaging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Adding ClockAnimation to Life3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 817-2FM.qxd 3/27/07 3:40 PM Page ix nCONTENTS ix The Desktop API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Using the Desktop Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 What Other Browser Capabilities Are There?. . . . . . . . . . . . . . . . . . . . . . . . 57 The System Tray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Creating Life3D’s Popup Menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 The Menu Contents. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Creating the TrayIcon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Building the Popup Menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Listening for Actions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Using a Text Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Launching an E-mail Client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Listening for the Check Boxes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Scripting in Java SE 6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Executing a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Communicating with a Script. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Speeding Things Up. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Calling Script Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Letting a Script Use Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 More Scripting Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Scripting in Life3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Initializing the Grid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Changing the Grid’s State. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Executing the Script Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 The Rules Script. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 nCHAPTER 4 The Colliding Grabbers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Building Articulated Arms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Class Diagrams for Arms3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Creating the Application Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Drawing the 3D Scene. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Processing the Keys. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Monitoring Grabber Joints. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Managing the Grabbers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Adding the Grabbers to the Scene Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Processing Keyboard Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Translating the Grabbers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Rotating a Grabber Joint. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Collecting the Collision Joints. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Collision Detection and Recovery. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Why Bother with JointsBehavior? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Touching the Floor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Description: