CoCalc Public Fileswww / talks / 2006-05-09-sage-digipen / tutorial / land-1.py
Author: William A. Stein
1# Soya 3D tutorial
2# Copyright (C) 2004      Jean-Baptiste 'Jiba'  LAMY
3# Copyright (C) 2001-2002 Bertrand 'blam!' LAMY
4#
5# This program is free software; you can redistribute it and/or modify
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
20# land-1: Landscape : bitmap-based landscape
21
22# This lesson shows how to make a landscape (also known as heightmap or terrain), using
23# a bitmap to describe the terrain. The bitmap acts like a popographic map ; the brighter
24# a pixel is, the higher it is. You can make such bitmaps in software like the Gimp.
25
26
27# Imports and inits Soya (see lesson basic-1.py).
28
29import sys, os, os.path, soya, soya.sdlconst
30
31soya.init()
32soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
33soya.set_quality(2)
34
35# Creates the scene.
36
37scene = soya.World()
38
39# Creates a new landscape in the scene.
40
41land = soya.Land(scene)
42
43# Gets the image "map1.png" from the tutorial data dir, and create the landscape
44# from this image. The image dimension must be power of 2 plus 1 : (2 ** n) + 1.
45
46land.from_image(soya.Image.get("map1.png"))
47
48# By default, the landscape height ranges from 0.0 (black pixels) to 1.0 (white pixels).
49# Here, we multiply the height by 8.0 so it ranges from 0.0 to 8.0.
50
51land.multiply_height(8.0)
52
53# Now that we have the landscape, we are going to texture it
54# (see lesson modeling-material-2 about texturing). First, we creates two textured
55# materials.
56
57#material1 = soya.Material(soya.Image.get("block2.png"))
58#material2 = soya.Material(soya.Image.get("metal1.png"))
59material1 = soya.Material.get("block2")
60material2 = soya.Material.get("metal1")
61
62#material1 = soya.Material()
63#material1.diffuse = (0.0, 0.0, 0.0, 1.0)
64#material1 = soya.Material.get("block2")
65#material2 = soya.Material()
66
67# asigns MATERIAL1 to any point whose height is in the range 0.0-6.0, and material2 to
68# any point whose height is in the range 6.0-8.0 (remember, height ranges from 0.0 to 8.0).
69
70land.set_material_layer(material1, 0.0, 6.0)
71land.set_material_layer(material2, 6.0, 8.0)
72
73# Assigns material1 to any point whose height is in the range 0.0-8.0 and if the angle
74# between the surface normal and the verticalvector is in the range 0.0-20.0.
75
76land.set_material_layer_angle(material1, 0.0, 8.0, 0.0, 20.0)
77
78# Now we set some Land attributes:
79#  - texture_factor specifies how much the textures are zoomed (higher values mean
80#    smaller texture)
81
82#  - scale_factor specifies how the landscape is scaled in the 2 horizontal dimensions.
83
84#  - the 2 last attributes influence the behaviour of the level of detail (LOD) algorithm
85#    (LOD means that parts of the landscape are rendered with more detail / more triangle
86#    if they are close to the camera). They are a trading between speed and quality.
87#
88#    The higher split_factor is, the better precision you have (it means more triangles
89#    to draw the Land even far from Camera).
90#
91#    patch_size represents the size of patches. A patch is a square part of the Land that
92#    computes its visibility and precision.
93
94# the values below are the default ones.
95
96land.texture_factor = 1.0
97land.scale_factor   = 1.0
98land.patch_size     = 8
99land.split_factor   = 2.0
100land.texture_factor = 0.25
101
102# Moves the landscape.
103
104land.y = -2.5
105
107
108light = soya.Light(scene)
109light.set_xyz(0.0, 15.0, 0.0)
110
111# Adds a keyboard-controlled camera and a rendering loop
112
113class MovableCamera(soya.Camera):
114  def __init__(self, parent):
115    soya.Camera.__init__(self, parent)
116
117    self.speed = soya.Vector(self)
118    self.rotation_lateral_speed  = 0.0
119    self.rotation_vertical_speed = 0.0
120
121  def begin_round(self):
122    soya.Camera.begin_round(self)
123
124    for event in soya.process_event():
125      if event[0] == soya.sdlconst.KEYDOWN:
126        if   event[1] == soya.sdlconst.K_UP:     self.speed.z = -1.0
127        elif event[1] == soya.sdlconst.K_DOWN:   self.speed.z =  1.0
128        elif event[1] == soya.sdlconst.K_LEFT:   self.rotation_lateral_speed =  10.0
129        elif event[1] == soya.sdlconst.K_RIGHT:  self.rotation_lateral_speed = -10.0
130        elif event[1] == soya.sdlconst.K_q:      soya.IDLER.stop()
131        elif event[1] == soya.sdlconst.K_ESCAPE: soya.IDLER.stop()
132      if event[0] == soya.sdlconst.KEYUP:
133        if   event[1] == soya.sdlconst.K_UP:     self.speed.z = 0.0
134        elif event[1] == soya.sdlconst.K_DOWN:   self.speed.z = 0.0
135        elif event[1] == soya.sdlconst.K_LEFT:   self.rotation_lateral_speed = 0.0
136        elif event[1] == soya.sdlconst.K_RIGHT:  self.rotation_lateral_speed = 0.0
137
140    self.turn_lateral (self.rotation_lateral_speed  * proportion)
141    self.turn_vertical(self.rotation_vertical_speed * proportion)
142
143
144camera = MovableCamera(scene)
145camera.set_xyz(16.0, 6.0, 0.0)
146camera.look_at(soya.Point(scene, 16.0, 6.0, 10.0))
147soya.set_root_widget(camera)
148
149
150#camera.set_xyz(16.0, 8.0, 0.0)
151#camera.look_at(soya.Point(scene, 16.0, 6.0, 10.0))
152
153
154scene.x = 100.0
155
156
157scene.atmosphere = soya.Atmosphere()
158scene.atmosphere.ambient = (1.0, 1.0, 1.0, 1.0)
159
160#soya.Idler(scene).idle()
161i = soya.Idler(scene)
162#i.min_frame_duration = 0.0
163i.idle()
164print i.fps
165