bugfix
[pyworlds.git] / src / pyworlds / utils.py
blob93da08b1e9fd869956b26e07b9ebc33748dfb066
1 import soya,math
3 def Face(x = 0,z = 0, plane = "XZ", parent = None, material = None, insert_into = None, texcoord_rect=(0,0,1,1), origin=(0,0,0)):
4 """Face(parent = None, material = None, insert_into = None) -> World
6 Creates and returns a World in PARENT, containing a face(x,y) length centered
7 on the origin, with material MATERIAL.
9 If INSERT_INTO is not None, the cube's faces are inserted into it, instead of
10 creating a new world.
12 The return value is a tuple of: ( World, Face, VertexArray )
14 plane is the plane where we want the face. Is one of: XZ, XY, YZ.
16 """
17 ox=origin[0]
18 oy=origin[1]
19 oz=origin[2]
21 face = insert_into or soya.World(parent)
22 r = texcoord_rect
23 tx1 = r[0]
24 tx2 = r[2]
26 ty1 = r[1]
27 ty2 = r[3]
28 if plane == "XZ":
29 vertex_array = [
30 soya.Vertex(face, 0.5*x+ox, oy, 0.5 * z+oz, tx2, ty2),
31 soya.Vertex(face, 0.5*x+ox, oy, -0.5 * z+oz, tx2, ty1),
32 soya.Vertex(face, -0.5*x+ox, oy, -0.5 * z+oz, tx1, ty1),
33 soya.Vertex(face, -0.5*x+ox, oy, 0.5 * z+oz, tx1, ty2),
35 elif plane == "XY":
36 vertex_array = [
37 soya.Vertex(face, 0.5*x+ox, 0.5 * z+oy, oz, tx2, ty2),
38 soya.Vertex(face, 0.5*x+ox, -0.5 * z+oy, oz, tx2, ty1),
39 soya.Vertex(face, -0.5*x+ox, -0.5 * z+oy, oz, tx1, ty1),
40 soya.Vertex(face, -0.5*x+ox, 0.5 * z+oy, oz, tx1, ty2),
42 elif plane == "YZ":
43 vertex_array = [
44 soya.Vertex(face, ox, 0.5*x+oy, 0.5 * z+oz, tx2, ty2),
45 soya.Vertex(face, ox, 0.5*x+oy, -0.5 * z+oz, tx2, ty1),
46 soya.Vertex(face, ox, -0.5*x+oy, -0.5 * z+oz, tx1, ty1),
47 soya.Vertex(face, ox, -0.5*x+oy, 0.5 * z+oz, tx1, ty2),
50 theface = soya.Face(face, vertex_array , material)
51 return face, theface, vertex_array
55 def xy_toangle(x1,y1):
56 h_xz=math.sqrt(x1*x1+y1*y1)
57 x=x1/h_xz
58 z=y1/h_xz
59 angle=math.asin(z)*180/math.pi
60 if x<0:
61 angle+=90 # place 0 degrees up
62 angle=-angle # mirror the result
63 angle-=90 # restore it.
65 if angle<0: angle+=360
67 return angle
71 def Box(x,y,z,parent = None, material = None, insert_into = None, texcoord_size=1, origin=(0,0,0), lit = True):
72 """Box(parent = None, material = None, insert_into = None) -> World
74 Creates and returns a World in PARENT, containing a box(x,y,z) length centered
75 on the origin, with material MATERIAL.
77 If INSERT_INTO is not None, the cube's faces are inserted into it, instead of
78 creating a new world."""
79 ox=origin[0]
80 oy=origin[1]
81 oz=origin[2]
83 cube = insert_into or soya.World(parent)
84 s = texcoord_size
85 f=soya.Face(cube, [soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 1.0*s, 1.0*s),
86 soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 0.0, 1.0*s),
87 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 0.0, 0.0),
88 soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 1.0*s, 0.0),
89 ], material)
90 f.lit = lit
92 f=soya.Face(cube, [soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 0.0, 1.0*s),
93 soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 0.0, 0.0),
94 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 1.0*s, 0.0),
95 soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 1.0*s, 1.0*s),
96 ], material)
98 f.lit = lit
100 f=soya.Face(cube, [soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 1.0*s, 0.0),
101 soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 1.0*s, 1.0*s),
102 soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 0.0, 1.0*s),
103 soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 0.0, 0.0),
104 ], material)
105 f.lit = lit
106 f=soya.Face(cube, [soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 1.0*s, 0.0),
107 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 1.0*s, 1.0*s),
108 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 0.0, 1.0*s),
109 soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 0.0, 0.0),
110 ], material)
111 f.lit = lit
113 f=soya.Face(cube, [soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 1.0*s, 1.0*s),
114 soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 1.0*s, 0.0),
115 soya.Vertex(cube, 0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 0.0, 0.0),
116 soya.Vertex(cube, 0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 0.0, 1.0*s),
117 ], material)
118 f.lit = lit
119 f=soya.Face(cube, [soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, 0.5 * z+oz, 0.0, 1.0*s),
120 soya.Vertex(cube, -0.5*x+ox, 0.5 * y+oy, -0.5 * z+oz, 1.0*s, 1.0*s),
121 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, -0.5 * z+oz, 1.0*s, 0.0),
122 soya.Vertex(cube, -0.5*x+ox, -0.5 * y+oy, 0.5 * z+oz, 0.0, 0.0),
123 ], material)
124 f.lit = lit
126 return cube
131 def Sphere(parent = None, material = None, quality = (10,10), smooth_lit = 1, insert_into = None,
132 texcoords=[(0,1),(0,1)], size=(1,1,1),position=(0,0,0)):
133 """Sphere(parent = None, material = None, slices = 20, stacks = 20, insert_into = None, min_tex_x = 0.0, max_tex_x = 1.0, min_tex_y = 0.0, max_tex_y = 1.0) -> World
135 Creates and returns a World in PARENT, containing a sphere of 1 radius centered
136 on the origin, with material MATERIAL.
138 SLICES and STACKS can be used to control the quality of the sphere.
140 If INSERT_INTO is not None, the sphere's faces are inserted into it, instead of
141 creating a new world.
143 MIN/MAX_TEX_X/Y can be used to limit the range of the texture coordinates to the given
144 values."""
145 from math import sin, cos
146 slices = quality[0]
147 stacks = quality[1]
149 min_tex_x = texcoords[0][0]
150 max_tex_x = texcoords[0][1]
151 min_tex_y = texcoords[1][0]
152 max_tex_y = texcoords[1][1]
154 px=position[0]
155 py=position[1]
156 pz=position[2]
158 sx=size[0]
159 sy=size[1]
160 sz=size[2]
163 sphere = insert_into or soya.World(parent)
165 step1 = 6.28322 / slices
166 step2 = 3.14161 / stacks
168 angle1 = 0.0
169 for i in xrange(slices):
170 angle2 = 0.0
171 j = 0
173 face = soya.Face(sphere, [
174 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 ) * sx + px, cos(angle2 ) * sy + py, sin(angle1 ) * sin(angle2 ) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j ) / stacks),
175 soya.Vertex(sphere, cos(angle1 + step1) * sin(angle2 + step2) * sx + px, cos(angle2 + step2) * sy + py, sin(angle1 + step1) * sin(angle2 + step2) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i + 1) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j + 1) / stacks),
176 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 + step2) * sx + px, cos(angle2 + step2) * sy + py, sin(angle1 ) * sin(angle2 + step2) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j + 1) / stacks),
177 ], material)
178 face.smooth_lit = smooth_lit
179 angle2 += step2
181 for j in range(1, stacks - 1):
182 face = soya.Face(sphere, [
183 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 ) * sx + px, cos(angle2 ) * sy + py, sin(angle1 ) * sin(angle2 ) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j ) / stacks),
184 soya.Vertex(sphere, cos(angle1 + step1) * sin(angle2 ) * sx + px, cos(angle2 ) * sy + py, sin(angle1 + step1) * sin(angle2 ) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i + 1) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j ) / stacks),
185 soya.Vertex(sphere, cos(angle1 + step1) * sin(angle2 + step2) * sx + px, cos(angle2 + step2) * sy + py, sin(angle1 + step1) * sin(angle2 + step2) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i + 1) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j + 1) / stacks),
186 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 + step2) * sx + px, cos(angle2 + step2) * sy + py, sin(angle1 ) * sin(angle2 + step2) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j + 1) / stacks),
187 ], material)
188 face.smooth_lit = smooth_lit
189 angle2 += step2
191 j = stacks - 1
193 face = soya.Face(sphere, [
194 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 ) * sx + px, cos(angle2 ) * sy + py, sin(angle1 ) * sin(angle2 ) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j ) / stacks),
195 soya.Vertex(sphere, cos(angle1 + step1) * sin(angle2 ) * sx + px, cos(angle2 ) * sy + py, sin(angle1 + step1) * sin(angle2 ) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i + 1) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j ) / stacks),
196 soya.Vertex(sphere, cos(angle1 ) * sin(angle2 + step2) * sx + px, cos(angle2 + step2) * sy + py, sin(angle1 ) * sin(angle2 + step2) * sz + pz, min_tex_x + (max_tex_x - min_tex_x) * float(i ) / slices, min_tex_y + (max_tex_y - min_tex_y) * float(j + 1) / stacks),
197 ], material)
198 face.smooth_lit = smooth_lit
200 angle1 += step1
202 return sphere
217 def look_at_elastic(self,p2,vector=None, factor=0.5, sqrt_from=15):
218 if p2 == None: raise Exception, "lookat_elastic: You must give at least the p2 parameter"
219 if vector == None:
220 vector = soya.Vector(self,0,0,-1000)
222 q=vector % self.parent # I mean an upper container.
224 v1 = (self >> q)
225 v2 = (self >> p2)
227 angle = v1.angle_to(v2)
229 v12 = v1.cross_product(v2)
230 a12 = v1.dot_product(v2)
231 if a12<0: angle = -angle
232 if abs(angle)>90: angle=-angle
233 v12.normalize()
234 if abs(angle) < 0.1:
235 return
236 if abs(angle) == 180.0: angle=180.1;
238 original_angle=angle
240 if angle>sqrt_from:
241 angle/=sqrt_from
242 angle=math.sqrt(angle)
243 angle*=sqrt_from
245 angle*=factor
247 self.rotate_axis(angle, v12)