Lab 6 Intro to 3D Graphics This tutorial is taken from Ray Diaz http://www.blitzbasic.com/Community/posts.php?topic=27913 And also samples code from Grant McGregor's StarWars3D program (on CSIS 196.1 website) Battle001 CREATING A SIMPLE GAME IN 3D Chapter I: The Scenery Overview: In order to create a game we need to provide several items that will give a backbone to the project: The environment for our characters The characters The Plot These three basic aspects can be defined as follows: The environment for our characters: The world they live in, and a way to see what they do. The characters: Good guys, bad guys, fill-in guys The plot : The rules of the game, as well as the story. The environment consists of The graphic setting The Lights Pivots Our Eyes: The camera The Sky The Floor (or terrain) Props The Graphic Setting {graphics3d width,height,depth,mode}1 {Setbuffer buffer} CODE ;graphics Remarks We have chosen 800 x 600, leaving the 1 The curly braces are quotations from the help manual. If you are not familiar with the command, refer to the help manual when the command is first mentioned to gain a better insight of the operation being carried out. Checking the help manual and trying out the examples will give you more confidence with the system 1 Graphics3D 800,600 SetBuffer BackBuffer() depth and mode to Blitz. We have chosen the back buffer as our drawing buffer The Light {createlight([type][,parent]} (RotateEntity entity,pitch#,yaw#,roll#[,global] CODE REMARKS ;light We have created a directional light by Global light = CreateLight() default, with no parents, and rotated it 90 RotateEntity light, 90,0,0 degrees to obtain light from above If you do not rotate the light it gives a dark hue. And if you rotate it 45 degrees it gives a sort of twilight. A pivot : the camera pivot {createpivot(parent} {entityRadius,entity,x#_radius[,y#_radius]} {entityType,entity,collision_type) We will create a pivot essentially to control the camera and other entities, such as the sky, so that when the pivot moves it will move the camera and the sky. The “entity radius” feature will be used to calculate collisions later. The “entity type” determines a category of entity used for collision checking. CODE Remarks ;CAMERA PIVOT Create the pivot, give it a radius camera_pivot= CreatePivot() (basically how fat and tall it will be), and EntityRadius camera_pivot,1.4 a type of PLAYER, which is defined in EntityType camera_pivot,PLAYER the global declarations as a number 2 Global PLAYER = 2 Collision Groups Collision groups will become important later; for now, we will just build a “Collisions Group” list below the Graphics entries. Code Remarks ;Collision Groups Global PLAYER = 2 Our eyes, the camera {CreateCamera (parent)} {cameraRange camera,near,far} {CamerafogMode,entity,mode} {CameraFogRange,entity,near,far} CODE ;CAMERA Global camera = CreateCamera(camera_pivot) CameraRange camera,1,1000 CameraFogMode camera,1 CameraFogRange camera,60,200 REMARKS Create a camera that will move when the camera pivot moves. In addition, set the parameters for range and fog. 2 We could look into our program if we wanted to, but we would see nothing yet. Once we have the ground and the sky, we will be able to look on a new world. The Sky {createSphere(segments)[,parent] {FlipMesh mesh} {ScaleEntity entity,x#_scale,y#_scale,z#_scale)[,global]} {PositionEntity entity,x#,y#,z# [,global]} {LoadTexture(File$[,flags])} {EntityTexture entity,texture} The technique used to create a credible sky is FlipMesh, a command that flips the triangles of a mesh so you can see the inside. We need any suitable sky picture for a texture. The one we used here was in the samples provided with Blitz3d, a 256 x 256 file in bmp format called “sky.bmp” CODE ;SKY Global sky = CreateSphere(16,camera_pivot) FlipMesh sky ScaleEntity sky,100,100,100 PositionEntity sky, 0,50,0 sky_tex = LoadTexture("sky.bmp") EntityTexture sky,sky_tex REMARKS We create a reasonable sphere with 16 segments, and specify the camera pivot as the parent, so that when the camera moves, the sky will move with it. Otherwise we might run out of sky very soon. Then we flip the mesh sky, scale it up to 100 times its original size, and position it 50 units high. Next, we create a texture from the bit map “sky”, with no special flags, and apply the texture to the mesh. The Terrain {loadterrain(file$[,parent])} {terraindetail(detail_level[,vertex_morph])} Height2.jpg Code ;TERRAIN Global terrain = LoadTerrain("height2.jpg") TerrainDetail terrain,2500,True ScaleEntity terrain, 3,15,3 Mossyground.bmp Remarks We load a “height map” as a terrain. This is a black and white bmp file where white is high, black is low, and shades of gray are differences in height. The terrain detail was set at 2500, with vertex morphing. Due to the nature of terrains, we make the 3 PositionEntity terrain,-1000,0,-530 ter_tex = LoadTexture("mossyground.bmp") EntityTexture terrain,ter_tex EntityRadius terrain,0.2 EntityType terrain,SCENERY Amend the Collisions groups as follows Code ;collision groups Global SCENERY = 1 Global PLAYER = 2 y dimension 15 times bigger, while making the x and z dimensions only 3 times bigger Next, we position the terrain under us so that we are well within it, not at the edge. We chose the famous “mossy ground” texture from the help file, media folder. Apply it, and finally establish a radius for the terrain of 0.2 so that we can check collisions Finally, make a type SCENERY, defined in globals as = 1 Remarks We have two groups for the moment. We will position the camera a bit above ground to see the scenery: CODE REMARKS PositionEntity Camera_pivot 0,10,120 This places the camera 10 units above ground level The Game Loop Now we need a game loop to see our creation so far: {MoveEntity entity,x#,y#,z#} {TurnEntity entity x#,y#,z#} {updateWorld} {renderWorld} CODE ;main loop While Not KeyHit(1) If KeyDown(200) MoveEntity camera_pivot,0,0,0.05 If KeyDown(208)MoveEntity camera_pivot,0,0,-0.05 If KeyDown(203) TurnEntity camera_pivot,0,2,0 If KeyDown(205)TurnEntity camera_pivot,0,-2,0 REMARKS The side cursor keys will turn the camera, and the forward and backward cursor keys will let you fly over the terrain. UpdateWorld RenderWorld Flip Wend End Run the program. This is a new, empty green world, which we will develop further in the next chapters. 4 Summary Of Resources: Sky.bmp Height2.jpg Mossyground.bmp Battle001.bb 256 x 256 BMP file 256 x 256 JPG file 256 x 256 BMP file Blitz 3d source file Radius65 Sept ‘03 Run the demo program ModifiedBattle001.bb. (Initially the same as Battle001.bb) Move around using arrow keys. Then try the following Modifications: 1. Under Light…change the rotation: 2. Read help entry on RotateEntity 3. Open RotateCone.bb, play with pitch, roll, yaw 4. Add these lines to RotateEntity light, 90,0,0 ModifiedBattle001.bb under ;Position the camera ;Position the camera PositionEntity camera_pivot,0,10,120 ; Create and position cone ADD cone=CreateCone( 32 ) ADD PositionEntity cone,0,10,140 ADD 5. Add more manueverability to Play with cone position and size ModifiedBattle001.bb ;main loop While Not KeyHit(1) If KeyDown(200) MoveEntity camera_pivot,0,0,0.05 If KeyDown(208) MoveEntity camera_pivot,0,0,-0.05 If KeyDown(203) TurnEntity camera_pivot,0,2,0 If KeyDown(205) TurnEntity camera_pivot,0,-2,0 If KeyDown(31) TurnEntity camera_pivot,2,0,0 ADD If KeyDown(32) TurnEntity camera_pivot,-2,0,0 ADD If KeyDown(44) MoveEntity camera_pivot,0,0.05,0 ADD If KeyDown(45) MoveEntity camera_pivot,0,-0.05,0 ADD up arrow forward down arrow backward left arrow turn left right arrow turn right letter s pitch back (up) letter d pitch fwd (dn) letter z move up letter x move down NOTES A) change the steps sizes is for larger jumps. Can you reach the edge of the world? B) How does the terrain map change the landscape? C) Magnify the vertical scale of the terrain map. Find this line: ScaleEntity terrain, 3,15,3 (change 15 to 50…what happens?) D) Set the scale back to 15 before doing next steps 5 Battle002 CREATING A SIMPLE GAME IN 3D CHAPTER II Keeping Your Feet On The Ground Overview: We are exploring the elements that will give a backbone to our project: The environment, the characters, and the plot. So far, we have seen the environment and created the graphic setting, the lights, a pivot, the camera, the sky, and the floor (or terrain). In this chapter we will begin by arming our hero, then we will take care of gravity in our world, discuss how to get our bearings, and we will plant down some floors to mark our first four settlements. Give the man a weapon Thanks to Psionic3d Design Resources (www.psionic3D.co.uk) we can use a 3D model of a gun, so that our hero does not go out defenseless. These are the commands you should look up in the help files: {Loadmesh(filename$[,parent])} {entityOrder, entity,var} Glocmap.jpg Add the following lines after Terrain and before Position the camera: CODE` REMARKS ;WEAPON psionic3d The commands used are falling into a repetitive sequence: Global weapon2 = LoadMesh("gloc.3ds",camera_pivot) Load mesh, weapon_tex2 = LoadTexture("glocmap.jpg") Load texture, EntityTexture weapon2,weapon_tex2 Assign it to the gun, RotateEntity weapon2,12,170,14 Rotate the entity until you are satisfied with the way the gun looks ScaleEntity weapon2,0.01,0.01,0.01 Scale the gun so that it looks reasonable PositionEntity weapon2,1,-1,1.5 Position the entity where you can see it (in this case a bit behind the camera, so that you only see part of it). EntityOrder weapon2, -1 The “entityOrder” command allows the weapon to be drawn last. The reason for this is to prevent the gun from “sinking” into other props. Because we are too high over the ground we should reposition ourselves a bit lower, to walk the earth: Change the position entity camera pivot command to PositionEntity camera_pivot,0,5.6,120 This will put us 5.6 units above ground. Go walking around 6 As we run the program we see an impressive mossy ground topped by a blue sky, and we see ourselves with a powerful gun in our hands. Full of self-confidence we start to move… and we go right through the moss. Our character is not responsive to the up and downs of the world. To solve this we need to reposition our camera pivot each time we move. This is the method given in the B3D help files, using the terrainY figure, which controls the terrain height. Let us say you are looking at a map on your desk. To your left is West, to your right is East, North is upwards, and South is downward. The distance from your eyes to the printed page is the Height (UP). In 3D coordinates these cardinal points are defined as follows: West = -X (negative values of X) East = +X (positive values of X) North = +Z (positive values of Z) South = -Z (negative values of Z) Height +Y (positive values of Y) If you went under the table and looked up, that would be a negative value of Y. And that is what is happening to our man: He is sinking under the ground. To correct this, we need to add some lines of code: Declare some globals right under graphics: ;GLOBALS Global x#,y#,z#,terra_y# Add the following code inside the main loop: {EntityX(entity[,global])} {EntityY(entity[,global])} (EntityZ(entity[,global])} {TerrainY(terrain,x#,y#,z#)} Code x#=EntityX(camera_pivot) y#=EntityY(camera_pivot) z#=EntityZ(camera_pivot) Remarks The current x value of the camera pivot The current Y value of the camera pivot The current Z value of the camera pivot Terra y# will take the resulting value of the composite TerrainY, which is an aggregate of the terrain values of x, y, and z, plus 1.6. Now, terrainY is equal to the terrain height at that particular point. Adding 1.6 on top ensures that the camera pivot will be ABOVE it by that much every cycle. terra_y#=TerrainY(terrain,x#,y#,z#)+1.6 7 PositionEntity camera_pivot,x#,terra_y#,z# Add these lines after Update World After we add those lines to our main loop our hero will never sink under the ground for long. If the ground is quite wild you may have to adjust the 1.6 value a bit. Try it. NOTES A) When you are ready, scale the terrain back to 50 or even 100 pr 200 and see what happens. Can you still rise up and down (z and x keys) can you look up or down (s and d keys) Populating the world. Lets make a moving object Grant has done some terrific work creating star wars models in his 3D star wars game (see online). This code creates a tie fighter from spheres and cylinders linked together: Code Remarks ; create and position tie fighter ball = CreateSphere () ScaleEntity ball, 0.5, 0.5, 0.5 RotateEntity ball, 90, 0, 90 PositionEntity ball, 10, 10, 170 sphere at core of fighter pole = CreateCylinder (18, True, ball) ScaleEntity pole, 0.25, 2.5, 0.25 the central pole in fighter twing = CreateCylinder (6, True, pole) ScaleEntity twing, 15, 0.1, 15 RotateEntity twing, 0, 30, 0 PositionEntity twing, 0, -1, 0 the hexagonal side panel twing2 = CopyEntity (twing, pole) PositionEntity twing2, 0, 1, 0 the other hex panel Copy and paste it into the program after where you created and positioned the cone. In order to make it move, add the following line at the bottom of the main game loop, before UpdateWorld: TranslateEntity ball, 0, 0, -0.2 Now run the game and watch the tie fighter fly by. You can play with modifying the camera movement routines to be able to chase the tie fighter. THAT'S IT!!! Hope you enjoyed the class! If you liked this, and want to explore programming further, check out in the spring: CSIS 10A Beginning C++ programming Tue/Thur 11:30 to 2 Starts 1/31/06 8