2
# Copyright (C) 2001-2002 Bertrand 'blam!' LAMY
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
# ---------------------
20
# Lesson 104: Landscape
21
# ---------------------
23
# This lesson shows how to make a landscape (also known as heightmap)
25
import random, os, os.path, sys, time
34
data_dir = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "data")
36
soya.model.Image .PATH = os.path.join(data_dir, "images")
37
soya.model.Material.PATH = os.path.join(data_dir, "materials")
38
soya.soya3d.World .PATH = os.path.join(data_dir, "worlds")
39
soya.model.Shape .PATH = os.path.join(data_dir, "shapes")
42
world = soya.soya3d.World()
45
light = soya.soya3d.Light(world)
46
light.set_xyz(0.0, 15.0, 0.0)
51
# There are 2 ways to create a landscape:
52
# 1) give each height value
53
# 2) create a landscape from an image (white pixels are upper)
56
land = soya.land.Land(land_size)
57
# Land_size is the size of the landscape. Landscapes are always squares
58
# and their size must always be like this : (2^n)+1
60
# The following lines set randomized value for each height
62
while (i < land_size):
64
while (j < land_size):
65
land.set_height(i, j, random.random())
69
# Multiply all the heights by 4
70
land.multiply_height(4.0)
72
# Now we must set a Material to the Land. Land must always have a Material
73
# even if it is None (None is a white Material)
75
while (i < land_size):
77
while (j < land_size):
78
land.set_material(i, j, None)
83
# Above lines are quite useless. Now we will see how to create a Land from
84
# an image and how to texture it quickly
88
land = soya.land.Land(0)
89
# The size of 0 will be overriden by the size of the image
90
land.from_image(soya.model.Image("map1.tga"))
91
# Heights range from 0.0 (black pixels) to 1.0 (white pixels)
92
land.multiply_height(8.0)
95
material1 = soya.model.Material()
96
material1.tex_filename = "block2.tga"
98
material2 = soya.model.Material()
99
material2.tex_filename = "metal1.tga"
101
# land.set_material_layer(MATERIAL, FROM, TO)
102
# Set to all points that have a height between FROM and TO the material
104
land.set_material_layer(material1, 0.0, 6.0)
105
land.set_material_layer(material2, 6.0, 8.0)
108
# land.set_material_layer_angle(MATERIAL, HEIGHT_FROM, HEIGHT_TO, ANGLE_FROM, ANGLE_TO)
109
# This function works just has the previous one but add 2 more arguments:
110
# ANGLE_FROM and ANGLE_TO.
111
# This means that all points of the land will have the given material
113
# - its height is between HEIGHT_FROM and HEIGHT_TO
114
# - its normal makes an angle with the horizontal plane that is between ANGLE_FROM
115
# and ANGLE_TO (expressed in degrees).
116
land.set_material_layer_angle(material1, 0.0, 8.0, 0.0, 20.0)
119
# Now we will see some Land attributes:
121
land.scale_factor = 1.5
122
# This is the distance between 2 consecutive heights that you have given
123
# to define the Land. This is quite like doing the following:
124
# world.scale(1.5, 1.0, 1.5)
125
# Default value is 1.5
127
land.texture_factor = 1.0
128
# This factor is applied to texture coordinates when rendering the Land.
129
# Default value is 1.0
132
land.split_factor = 4.0
133
# These 2 values influence the behaviour of the level of detail algorithm
134
# (it means that there are more triangles to draw the Land near the Camera
135
# and less far from the Camera).
136
# The higher split_factor is, the better precision you have (it means more
137
# triangles to draw the Land even at long distance from Camera).
138
# map_size represents the size of a map. A map is a square part of the Land
139
# that computes its visibility and precision.
140
# map_size and split_factor values can change FPS (rendering speed). Values
141
# above are default ones (I get the best FPS with these ones on my computer)
144
# Land is a shape (and so can't be added in a World but must be set as shape)
145
world.set_shape(land)
148
# Add a camera and a loop to render
150
camera = soya.soya3d.Camera(world)
151
camera.set_xyz (16.0, 8.0, 0.0)
152
camera.look_at (soya.soya3d.Point (world, 16.0, 6.0, 10.0))
153
soya.set_root_widget(camera)
161
# Use Up, Down, Left, Right arrows to move the camera
163
for event in soya.process_event():
164
if event[0] == soya.KEYDOWN:
165
if event[1] == soya.K_UP:
166
camera.translate(0.0, 0.0, 0.5)
167
elif event[1] == soya.K_DOWN:
168
camera.translate(0.0, 0.0, -0.5)
169
elif event[1] == soya.K_LEFT:
170
camera.translate(0.5, 0.0, 0.0)
171
elif event[1] == soya.K_RIGHT:
172
camera.translate(-0.5, 0.0, 0.0)
173
elif event[1] == soya.K_q:
177
# Other Land functions not aborded in this tutorial (easy to understand):
178
# -----------------------------------------------------------------------
179
# height = land.get_height(x, z)
180
# material = land.get_material(x, z)
181
# land.add_height(value)
182
# [x and z are integers, value and height are floats]