Sharedwww / talks / 2006-05-09-sage-digipen / tutorial / basic-4.pyOpen in CoCalc
Author: William A. Stein
1
# Soya 3D tutorial
2
# Copyright (C) 2004 Jean-Baptiste LAMY
3
#
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.
8
#
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.
13
#
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
17
18
19
# basic-4: Time management : a randomly moving caterpillar
20
21
# In this lesson, we'll creates a caterpillar composed of a head (we've already done it
22
# in the previous lesson ; now you understand why i have called it a 'head') and ten
23
# spherish piece of body. Each piece of body follows the previous one, or the head for
24
# first piece.
25
26
# Run the tutorial if you don't understand well what is the caterpillar.
27
28
29
# Import the Soya module.
30
31
import sys, os, os.path, random, soya
32
33
soya.init()
34
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
35
36
# Creates a scene.
37
38
scene = soya.World()
39
40
# CaterpillarHead is the class for the head of the caterpillar.
41
# It is identical to the Head class of lesson basic-3.py, except the class name.
42
# So... no comment!
43
44
class CaterpillarHead(soya.Volume):
45
def __init__(self, parent):
46
soya.Volume.__init__(self, parent, soya.Shape.get("caterpillar_head"))
47
self.speed = soya.Vector(self, 0.0, 0.0, -0.2)
48
49
def begin_round(self):
50
soya.Volume.begin_round(self)
51
52
self.rotate_lateral((random.random() - 0.5) * 50.0)
53
54
def advance_time(self, proportion):
55
soya.Volume.advance_time(self, proportion)
56
57
self.add_mul_vector(proportion, self.speed)
58
59
60
# A CaterpillarPiece is a piece of the body of the caterpillar.
61
# It follows another object -- the previous piece, or the head for the first one.
62
63
class CaterpillarPiece(soya.Volume):
64
65
# The constructor takes two arguments: the parent and the previous piece of body that
66
# we must follow.
67
# Similarly to the head, we define a speed vector.
68
69
def __init__(self, parent, previous):
70
soya.Volume.__init__(self, parent, soya.Shape.get("caterpillar"))
71
self.previous = previous
72
self.speed = soya.Vector(self, 0.0, 0.0, -0.2)
73
74
def begin_round(self):
75
soya.Volume.begin_round(self)
76
77
# We rotates the caterpillar piece so as it looks toward the previous piece.
78
79
self.look_at(self.previous)
80
81
# The distance_to method returns the distance between two position.
82
# If we are too close to the previous piece of body, we set the speed's Z to 0.0,
83
# and thus the speed is a null vector : this piece no longer moves.
84
85
# Else, we reset the speed's Z to -0.2.
86
87
if self.distance_to(self.previous) < 1.5: self.speed.z = 0.0
88
else: self.speed.z = -0.2
89
90
# advance_time is identical to the CaterpillarHead ones.
91
92
def advance_time(self, proportion):
93
soya.Volume.advance_time(self, proportion)
94
95
self.add_mul_vector(proportion, self.speed)
96
97
98
# Creates a caterpillar head.
99
100
caterpillar_head = CaterpillarHead(scene)
101
caterpillar_head.rotate_lateral(90.0)
102
103
# Creates 10 caterpillar piece of body.
104
105
previous_caterpillar_piece = caterpillar_head
106
for i in range(10):
107
previous_caterpillar_piece = CaterpillarPiece(scene, previous_caterpillar_piece)
108
previous_caterpillar_piece.x = i + 1
109
110
# Creates a light.
111
112
light = soya.Light(scene)
113
light.set_xyz(2.0, 5.0, 0.0)
114
115
# Creates a camera.
116
117
camera = soya.Camera(scene)
118
camera.set_xyz(0.0, 15.0, 15.0)
119
camera.look_at(caterpillar_head)
120
soya.set_root_widget(camera)
121
122
soya.Idler(scene).idle()
123
124
125
# For information, the caterpillar textures were done in the Gimp, and the model were
126
# generated with this code (see modeling-*.py to understand it) :
127
128
# import soya.sphere
129
# caterpillar_material = soya.Material(soya.Image.get("chenille.png" ))
130
# caterpillar_head_material = soya.Material(soya.Image.get("chenille_tete.png"))
131
# caterpillar_material .filename = "caterpillar"
132
# caterpillar_head_material.filename = "caterpillar_head"
133
# caterpillar_material .save()
134
# caterpillar_head_material.save()
135
136
# caterpillar = soya.sphere.Sphere(slices = 12, stacks = 12, material = caterpillar_material)
137
# caterpillar_head = soya.sphere.Sphere(slices = 12, stacks = 12, material = caterpillar_head_material)
138
# caterpillar_head.scale(1.2, 1.2, 1.2)
139
# caterpillar .filename = "caterpillar"
140
# caterpillar_head.filename = "caterpillar_head"
141
# caterpillar .save()
142
# caterpillar_head.save()
143
144
145
146
147
148
149
150
151
152
153
154
155
# XXX put this elsewhere
156
157
# Lots of Soya methods have also an operator :
158
#
159
# Position + Vector => Point
160
# Position += Vector Position.add_vector(Vector)
161
# Position >> Position Position.vector_to (Position) => Vector
162
# Position %= CoordSyst Position.convert_to(CoordSyst)
163
# Vector * float
164
165
# Position + Vector => Point
166
167
# Position += Vector
168
# Position.add_vector(Vector)
169
# Translation or vectorial addition (if the Position is a Vector).
170
171
# Position >> Position => Vector
172
# Position.vector_to (Position) => Vector
173
# Creates a vector from a strating and an ending position.
174
175
# Position %= CoordSyst Position.convert_to(CoordSyst)
176
# Vector * float
177