threequick 0.0.0__tar.gz → 0.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {threequick-0.0.0/src/threequick.egg-info → threequick-0.0.2}/PKG-INFO +3 -3
- threequick-0.0.2/README.md +2 -0
- {threequick-0.0.0 → threequick-0.0.2}/pyproject.toml +1 -1
- threequick-0.0.2/scripts/example.py +98 -0
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick/__init__.py +1 -1
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick/threequick.py +116 -63
- {threequick-0.0.0 → threequick-0.0.2/src/threequick.egg-info}/PKG-INFO +3 -3
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick.egg-info/SOURCES.txt +2 -0
- threequick-0.0.2/src/threequick.egg-info/scm_file_list.json +12 -0
- threequick-0.0.2/src/threequick.egg-info/scm_version.json +8 -0
- threequick-0.0.0/README.md +0 -2
- threequick-0.0.0/scripts/example.py +0 -68
- {threequick-0.0.0 → threequick-0.0.2}/.gitignore +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/LICENSE +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/scripts/build-install-test.sh +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/setup.cfg +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick.egg-info/dependency_links.txt +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick.egg-info/requires.txt +0 -0
- {threequick-0.0.0 → threequick-0.0.2}/src/threequick.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threequick
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: A simple python library for creating 3D visualisations
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: A simple python library for creating 3D visualisations
|
|
5
5
|
Author-email: Hannah Baldwin <contact@hannahbaldwin.net>
|
|
6
6
|
License: GPL-3.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/habaldwin01/threequick
|
|
@@ -16,4 +16,4 @@ Requires-Dist: pygame>=2.0.0
|
|
|
16
16
|
Dynamic: license-file
|
|
17
17
|
|
|
18
18
|
# threequick
|
|
19
|
-
A simple python library for creating 3D visualisations
|
|
19
|
+
A simple python library for creating 3D visualisations.
|
|
@@ -5,7 +5,7 @@ authors = [
|
|
|
5
5
|
{ name="Hannah Baldwin", email="contact@hannahbaldwin.net" },
|
|
6
6
|
]
|
|
7
7
|
license = { text="GPL-3.0" }
|
|
8
|
-
description = "A simple python library for creating 3D visualisations
|
|
8
|
+
description = "A simple python library for creating 3D visualisations"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.6"
|
|
11
11
|
classifiers = [
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
import math
|
|
4
|
+
from threequick import CameraContext, Object3d, Cube, Sphere, PointCloud
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
window = pygame.display.set_mode((1280, 720), pygame.RESIZABLE)
|
|
8
|
+
pygame.display.set_caption("threequick test")
|
|
9
|
+
done = False
|
|
10
|
+
renderable_objects = []
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
tc = Cube(0.2)
|
|
14
|
+
# pitch roll yaw
|
|
15
|
+
# x y z
|
|
16
|
+
#tc.set_rotation(0,0,0)
|
|
17
|
+
#tc.set_position(0,0,0)
|
|
18
|
+
tc.set_rotation(30,10,60)
|
|
19
|
+
tc.set_position(1,0,0)
|
|
20
|
+
renderable_objects.append(tc)
|
|
21
|
+
|
|
22
|
+
sp = Sphere(16, 6+1, 1)
|
|
23
|
+
renderable_objects.append(sp)
|
|
24
|
+
|
|
25
|
+
#point_cloud = PointCloud()
|
|
26
|
+
#renderable_objects.append(point_cloud)
|
|
27
|
+
|
|
28
|
+
#point_cloud.add_point([0,0.25,0.25], [0,255,0])
|
|
29
|
+
|
|
30
|
+
cam_dist = 5
|
|
31
|
+
|
|
32
|
+
camera_context = CameraContext([0,-cam_dist,0], [70,0,30], 90, window)
|
|
33
|
+
camera_context.position[0] = (math.sin(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
34
|
+
camera_context.position[1] = (math.cos(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
35
|
+
camera_context.position[2] = math.cos(math.radians(camera_context.rotation[0])) * -cam_dist
|
|
36
|
+
|
|
37
|
+
cube_angle = 0
|
|
38
|
+
|
|
39
|
+
pygame.init()
|
|
40
|
+
|
|
41
|
+
last_ticks = pygame.time.get_ticks()
|
|
42
|
+
|
|
43
|
+
while not done:
|
|
44
|
+
current_ticks = pygame.time.get_ticks()
|
|
45
|
+
|
|
46
|
+
pygame.draw.rect(window, (0, 0, 0), (0, 0, window.get_width(), window.get_height()))
|
|
47
|
+
|
|
48
|
+
mx, my = pygame.mouse.get_pos()
|
|
49
|
+
for event in pygame.event.get():
|
|
50
|
+
if event.type == pygame.QUIT:
|
|
51
|
+
exit()
|
|
52
|
+
|
|
53
|
+
left_button, middle_button, right_button = pygame.mouse.get_pressed()
|
|
54
|
+
if not left_button:
|
|
55
|
+
last_rc_pos = (mx, my)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if left_button:
|
|
59
|
+
camera_context.rotation[0] -= (my - last_rc_pos[1]) * 0.2
|
|
60
|
+
if camera_context.rotation[0] > 180:
|
|
61
|
+
camera_context.rotation[0] = 180
|
|
62
|
+
if camera_context.rotation[0] < 0:
|
|
63
|
+
camera_context.rotation[0] = 0
|
|
64
|
+
smx = (math.sin(math.radians(camera_context.rotation[0]))) + 0.5
|
|
65
|
+
camera_context.rotation[2] -= (mx - last_rc_pos[0]) * 0.2 / smx
|
|
66
|
+
last_rc_pos = (mx, my)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
orbital_period_s = 8
|
|
70
|
+
cube_angle = ((pygame.time.get_ticks() / 1000) / orbital_period_s) * 360
|
|
71
|
+
|
|
72
|
+
tc.set_rotation(30,10,60 + cube_angle)
|
|
73
|
+
tc.set_position(math.sin(math.radians(cube_angle)),-math.cos(math.radians(cube_angle)),0)
|
|
74
|
+
#tc.set_position(0,0,0)
|
|
75
|
+
|
|
76
|
+
# Slow rotation of camera
|
|
77
|
+
#camera_context.rotation[2] += (last_ticks - current_ticks) / 80
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Calculate camera position based off angle so it always points at 0,0,0
|
|
81
|
+
camera_context.position[0] = (math.sin(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
82
|
+
camera_context.position[1] = (math.cos(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
83
|
+
camera_context.position[2] = math.cos(math.radians(camera_context.rotation[0])) * -cam_dist
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
last_ticks = current_ticks
|
|
87
|
+
|
|
88
|
+
camera_context.update_screenspace()
|
|
89
|
+
for ro in renderable_objects:
|
|
90
|
+
ro.draw(camera_context)
|
|
91
|
+
|
|
92
|
+
for event in pygame.event.get():
|
|
93
|
+
if event.type == pygame.QUIT:
|
|
94
|
+
done = True
|
|
95
|
+
|
|
96
|
+
pygame.display.flip()
|
|
97
|
+
|
|
98
|
+
exit()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
from .threequick import CameraContext, Object3d, Cube, Sphere, PointCloud
|
|
1
|
+
from .threequick import CameraContext, Object3d, Cube, Sphere, PointCloud, Ellipsoid
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import pygame
|
|
2
|
+
import pygame.font
|
|
2
3
|
import numpy as np
|
|
3
4
|
import math
|
|
5
|
+
import random
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
|
|
8
|
+
pygame.font.init()
|
|
9
|
+
sans_font = pygame.font.Font(pygame.font.get_default_font(), 36)
|
|
4
10
|
|
|
5
11
|
def transform_3d_point_4x4_mat(matrix, point):
|
|
6
12
|
# Convert to homogeneous coordinates
|
|
@@ -42,10 +48,12 @@ class CameraContext:
|
|
|
42
48
|
def __init__(self,
|
|
43
49
|
position: list[float],
|
|
44
50
|
rotation: list[float],
|
|
51
|
+
fov: float,
|
|
45
52
|
surface: pygame.Surface):
|
|
46
53
|
self.position = position
|
|
47
54
|
self.rotation = rotation
|
|
48
55
|
self.screen_size = (1,1)
|
|
56
|
+
self.fov = fov
|
|
49
57
|
self.frustum_width = 1
|
|
50
58
|
self.frustum_height = 1
|
|
51
59
|
self.surface = surface
|
|
@@ -54,13 +62,13 @@ class CameraContext:
|
|
|
54
62
|
self.screen_size = (self.surface.get_width(), self.surface.get_height())
|
|
55
63
|
|
|
56
64
|
self.min_render_distance = 0.1
|
|
57
|
-
self.frustum_width = self.min_render_distance
|
|
65
|
+
self.frustum_width = self.min_render_distance / (math.pi - math.radians(self.fov))
|
|
58
66
|
self.frustum_height = self.frustum_width * (self.screen_size[1] / self.screen_size[0])
|
|
59
67
|
#self.projection_matrix = [[nx/2, 0, 0, (nx-1)/2],
|
|
60
68
|
# [0, ny/2, 0, (ny-1)/2],
|
|
61
69
|
# [0, 0, 1/2, 1/2 ]]
|
|
62
70
|
|
|
63
|
-
f =
|
|
71
|
+
f = 10 # far
|
|
64
72
|
n = self.min_render_distance # near
|
|
65
73
|
r = self.frustum_width # width
|
|
66
74
|
t = self.frustum_height # height
|
|
@@ -73,6 +81,8 @@ class CameraContext:
|
|
|
73
81
|
[0, 0, c, d],
|
|
74
82
|
[0, 0,-1, 0]]
|
|
75
83
|
|
|
84
|
+
# From https://songho.ca/opengl/gl_transform.html
|
|
85
|
+
|
|
76
86
|
self.translation_matrix = [[1, 0, 0, self.position[0]],
|
|
77
87
|
[0, 1, 0, self.position[1]],
|
|
78
88
|
[0, 0, 1, self.position[2]],
|
|
@@ -103,71 +113,109 @@ class Renderable():
|
|
|
103
113
|
class Object3d(Renderable):
|
|
104
114
|
def __init__(self,
|
|
105
115
|
vertices: list[list[float]],
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
self.
|
|
110
|
-
self.
|
|
116
|
+
faces: list[list[int]],
|
|
117
|
+
color: Optional[list[int]] = None,
|
|
118
|
+
face_color: list[int] = None) -> None:
|
|
119
|
+
self.__mod_vertices = [None] * len(vertices)
|
|
120
|
+
#self.__mod_edges = edges
|
|
121
|
+
#self.__mod_faces = faces
|
|
111
122
|
self.vertices = vertices
|
|
112
|
-
self.edges = edges
|
|
113
123
|
self.faces = faces
|
|
114
|
-
self.
|
|
115
|
-
self.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
124
|
+
self.face_color = face_color
|
|
125
|
+
self.position = [0, 0, 0]
|
|
126
|
+
self.color = color
|
|
127
|
+
self.rotation_matrix = pry_rot_to_4x4(0, 0, 0)
|
|
128
|
+
self.update_vertex_cache()
|
|
129
|
+
edges = set()
|
|
130
|
+
for face in self.faces:
|
|
131
|
+
edges.add((face[0], face[1]))
|
|
132
|
+
edges.add((face[1], face[2]))
|
|
133
|
+
edges.add((face[2], face[0]))
|
|
134
|
+
self.edges = list(edges)
|
|
135
|
+
if self.color is None:
|
|
136
|
+
if self.face_color is None:
|
|
137
|
+
self.face_color = []
|
|
138
|
+
for face in self.faces:
|
|
139
|
+
self.face_color.append([random.randint(0,255),random.randint(0,255),random.randint(0,255)])
|
|
140
|
+
|
|
141
|
+
for face_idx in range(len(self.faces)):
|
|
142
|
+
print(str(self.faces[face_idx]) + " => " + str(self.face_color[face_idx]))
|
|
119
143
|
|
|
120
144
|
def set_rotation(self, pitch, roll, yaw):
|
|
121
145
|
self.rotation_matrix = pry_rot_to_4x4(pitch, roll, yaw)
|
|
122
|
-
|
|
123
|
-
for vindex, vertex in enumerate(self.vertices):
|
|
124
|
-
self.__mod_vertices[vindex] = transform_3d_point_4x4_mat(self.rotation_matrix, vertex)
|
|
146
|
+
self.update_vertex_cache()
|
|
125
147
|
|
|
126
148
|
def set_position(self, x, y, z):
|
|
127
149
|
self.position = [x, y, z]
|
|
150
|
+
self.update_vertex_cache()
|
|
128
151
|
|
|
152
|
+
def update_vertex_cache(self):
|
|
129
153
|
for vindex, vertex in enumerate(self.vertices):
|
|
154
|
+
vertex = transform_3d_point_4x4_mat(self.rotation_matrix, vertex)
|
|
130
155
|
self.__mod_vertices[vindex] = [vertex[0] + self.position[0], vertex[1] + self.position[1], vertex[2] + self.position[2]]
|
|
131
156
|
|
|
132
|
-
def
|
|
157
|
+
def draw_wireframe(self, camera_context: CameraContext) -> None:
|
|
133
158
|
scr_center = (camera_context.screen_size[0] / 2, camera_context.screen_size[1] / 2)
|
|
134
159
|
tpf = camera_context.transform_point
|
|
135
160
|
for edge in self.edges:
|
|
136
161
|
p1 = tpf(self.__mod_vertices[edge[0]])
|
|
137
162
|
p2 = tpf(self.__mod_vertices[edge[1]])
|
|
138
163
|
if p1 is not None and p2 is not None:
|
|
139
|
-
pygame.draw.line(camera_context.surface,
|
|
164
|
+
pygame.draw.line(camera_context.surface, self.color, p1, p2)
|
|
165
|
+
|
|
166
|
+
def draw(self, camera_context: CameraContext) -> None:
|
|
167
|
+
scr_center = (camera_context.screen_size[0] / 2, camera_context.screen_size[1] / 2)
|
|
168
|
+
tpf = camera_context.transform_point
|
|
169
|
+
for idx, face in enumerate(self.faces):
|
|
170
|
+
poly_points = [tpf(self.__mod_vertices[face[0]]),
|
|
171
|
+
tpf(self.__mod_vertices[face[1]]),
|
|
172
|
+
tpf(self.__mod_vertices[face[2]])]
|
|
173
|
+
|
|
174
|
+
dir_sum = 0
|
|
175
|
+
for edgeidx in range(3):
|
|
176
|
+
p1 = poly_points[edgeidx]
|
|
177
|
+
p2 = poly_points[(edgeidx + 1) % 3]
|
|
178
|
+
dir_sum += (p2[0] - p1[0]) * (p2[1] + p1[1])
|
|
179
|
+
backface_cull = dir_sum < 0
|
|
180
|
+
|
|
181
|
+
#if not backface_cull:
|
|
182
|
+
if self.color is None:
|
|
183
|
+
if backface_cull:
|
|
184
|
+
#pygame.draw.lines(camera_context.surface, self.face_color[idx], True, poly_points)
|
|
185
|
+
pass
|
|
186
|
+
else:
|
|
187
|
+
pygame.draw.polygon(camera_context.surface, self.face_color[idx], poly_points)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
#for ptidx in range(3):
|
|
191
|
+
# text_surface = sans_font.render(str(face[ptidx]), False, (255,255,255))
|
|
192
|
+
# camera_context.surface.blit(text_surface, poly_points[ptidx])
|
|
193
|
+
else:
|
|
194
|
+
if not backface_cull:
|
|
195
|
+
pygame.draw.polygon(camera_context.surface, self.color, poly_points)
|
|
196
|
+
|
|
140
197
|
|
|
141
198
|
class Cube(Object3d):
|
|
142
|
-
edges: list[list[int]] = [
|
|
143
|
-
[0, 1],
|
|
144
|
-
[1, 2],
|
|
145
|
-
[2, 3],
|
|
146
|
-
[3, 0],
|
|
147
|
-
[4, 5],
|
|
148
|
-
[5, 6],
|
|
149
|
-
[6, 7],
|
|
150
|
-
[7, 4],
|
|
151
|
-
[0, 4],
|
|
152
|
-
[1, 5],
|
|
153
|
-
[2, 6],
|
|
154
|
-
[3, 7]
|
|
155
|
-
]
|
|
156
199
|
faces: list[list[int]] = [
|
|
157
|
-
[0,
|
|
158
|
-
[
|
|
159
|
-
|
|
160
|
-
[
|
|
161
|
-
[
|
|
162
|
-
|
|
163
|
-
[
|
|
164
|
-
[2,
|
|
165
|
-
|
|
166
|
-
[
|
|
167
|
-
[
|
|
168
|
-
|
|
200
|
+
[0,1,2],
|
|
201
|
+
[0,2,3],
|
|
202
|
+
|
|
203
|
+
[4,7,6],
|
|
204
|
+
[6,5,4],
|
|
205
|
+
|
|
206
|
+
[5,2,1],
|
|
207
|
+
[6,2,5],
|
|
208
|
+
|
|
209
|
+
[5,1,4],
|
|
210
|
+
[4,1,0],
|
|
211
|
+
|
|
212
|
+
[7,0,3],
|
|
213
|
+
[4,0,7],
|
|
214
|
+
|
|
215
|
+
[7,3,6],
|
|
216
|
+
[6,3,2]
|
|
169
217
|
]
|
|
170
|
-
def __init__(self, size) -> None:
|
|
218
|
+
def __init__(self, size, color = None) -> None:
|
|
171
219
|
size = size/2
|
|
172
220
|
vertices: list[list[float]] = [
|
|
173
221
|
[-size, -size, -size],
|
|
@@ -179,17 +227,17 @@ class Cube(Object3d):
|
|
|
179
227
|
[size, size, size],
|
|
180
228
|
[-size, size, size]
|
|
181
229
|
]
|
|
182
|
-
super().__init__(vertices, Cube.
|
|
230
|
+
super().__init__(vertices, Cube.faces, color)
|
|
183
231
|
|
|
184
|
-
class
|
|
185
|
-
def __init__(self, n_meridians, n_parallels, diameter) -> None:
|
|
232
|
+
class Ellipsoid(Object3d):
|
|
233
|
+
def __init__(self, n_meridians, n_parallels, diameter, flattening, color = None) -> None:
|
|
234
|
+
compression_factor = 1 - flattening
|
|
186
235
|
radius = diameter/2
|
|
187
|
-
vertices = [[0,0,radius],[0,0,-radius]]
|
|
188
|
-
edges = []
|
|
236
|
+
vertices = [[0,0,radius * compression_factor],[0,0,-radius * compression_factor]]
|
|
189
237
|
faces = []
|
|
190
238
|
for ipa in range(n_parallels):
|
|
191
239
|
vang = ((ipa + 1) / (n_parallels + 1)) * math.pi
|
|
192
|
-
vpos = -math.cos(vang) * radius
|
|
240
|
+
vpos = -math.cos(vang) * radius * compression_factor
|
|
193
241
|
for ime in range(n_meridians):
|
|
194
242
|
ang = (ime * math.pi * 2) / n_meridians
|
|
195
243
|
sa = math.sin(ang)
|
|
@@ -199,24 +247,29 @@ class Sphere(Object3d):
|
|
|
199
247
|
|
|
200
248
|
# bottom cap
|
|
201
249
|
for ime in range(n_meridians):
|
|
202
|
-
|
|
250
|
+
faces.append([2+ime,1,2+((ime+1)%n_meridians)])
|
|
203
251
|
|
|
204
252
|
# top cap
|
|
205
253
|
for ime in range(n_meridians):
|
|
206
|
-
|
|
254
|
+
bc_offset = (n_meridians * (n_parallels - 1))
|
|
255
|
+
faces.append([0,2+ime+bc_offset,2+((ime+1)%n_meridians)+bc_offset])
|
|
207
256
|
|
|
208
|
-
#
|
|
257
|
+
# panels
|
|
209
258
|
for ipa in range(n_parallels - 1):
|
|
210
259
|
for ime in range(n_meridians):
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
260
|
+
pt1 = 2+((ime + 0)%n_meridians)+(n_meridians * ipa)
|
|
261
|
+
pt2 = 2+((ime + 0)%n_meridians)+(n_meridians * (ipa + 1))
|
|
262
|
+
pt3 = 2+((ime + 1)%n_meridians)+(n_meridians * ipa)
|
|
263
|
+
pt4 = 2+((ime + 1)%n_meridians)+(n_meridians * (ipa + 1))
|
|
264
|
+
faces.append([pt2, pt1, pt3])
|
|
265
|
+
faces.append([pt2, pt3, pt4])
|
|
266
|
+
#edges.append([2+ime+(n_meridians * (ipa + 1)),2+ime+(n_meridians * ipa)])
|
|
267
|
+
|
|
268
|
+
super().__init__(vertices, faces, color)
|
|
269
|
+
|
|
270
|
+
class Sphere(Ellipsoid):
|
|
271
|
+
def __init__(self, n_meridians, n_parallels, diameter, color = None) -> None:
|
|
272
|
+
super().__init__(n_meridians, n_parallels, diameter, 0, color)
|
|
220
273
|
|
|
221
274
|
class PointCloud(Renderable):
|
|
222
275
|
def __init__(self, diameter = 2) -> None:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threequick
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: A simple python library for creating 3D visualisations
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: A simple python library for creating 3D visualisations
|
|
5
5
|
Author-email: Hannah Baldwin <contact@hannahbaldwin.net>
|
|
6
6
|
License: GPL-3.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/habaldwin01/threequick
|
|
@@ -16,4 +16,4 @@ Requires-Dist: pygame>=2.0.0
|
|
|
16
16
|
Dynamic: license-file
|
|
17
17
|
|
|
18
18
|
# threequick
|
|
19
|
-
A simple python library for creating 3D visualisations
|
|
19
|
+
A simple python library for creating 3D visualisations.
|
|
@@ -10,4 +10,6 @@ src/threequick.egg-info/PKG-INFO
|
|
|
10
10
|
src/threequick.egg-info/SOURCES.txt
|
|
11
11
|
src/threequick.egg-info/dependency_links.txt
|
|
12
12
|
src/threequick.egg-info/requires.txt
|
|
13
|
+
src/threequick.egg-info/scm_file_list.json
|
|
14
|
+
src/threequick.egg-info/scm_version.json
|
|
13
15
|
src/threequick.egg-info/top_level.txt
|
threequick-0.0.0/README.md
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import pygame
|
|
2
|
-
import numpy as np
|
|
3
|
-
import math
|
|
4
|
-
from threequick import CameraContext, Object3d, Cube, Sphere, PointCloud
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
window = pygame.display.set_mode((1280, 720), pygame.RESIZABLE)
|
|
8
|
-
pygame.display.set_caption("threequick test")
|
|
9
|
-
done = False
|
|
10
|
-
renderable_objects = []
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
tc = Cube(0.2)
|
|
14
|
-
# pitch roll yaw
|
|
15
|
-
# x y z
|
|
16
|
-
tc.set_rotation(30,10,60)
|
|
17
|
-
renderable_objects.append(tc)
|
|
18
|
-
|
|
19
|
-
sp = Sphere(16, 6+1, 1)
|
|
20
|
-
renderable_objects.append(sp)
|
|
21
|
-
|
|
22
|
-
point_cloud = PointCloud()
|
|
23
|
-
renderable_objects.append(point_cloud)
|
|
24
|
-
|
|
25
|
-
point_cloud.add_point([0,0.25,0.25], [0,255,0])
|
|
26
|
-
|
|
27
|
-
cam_dist = 2
|
|
28
|
-
|
|
29
|
-
camera_context = CameraContext([0,-cam_dist,0], [90,0,0], window)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
while not done:
|
|
33
|
-
pygame.draw.rect(window, (0, 0, 0), (0, 0, 1280, 720))
|
|
34
|
-
|
|
35
|
-
mx, my = pygame.mouse.get_pos()
|
|
36
|
-
for event in pygame.event.get():
|
|
37
|
-
if event.type == pygame.QUIT:
|
|
38
|
-
exit()
|
|
39
|
-
|
|
40
|
-
left_button, middle_button, right_button = pygame.mouse.get_pressed()
|
|
41
|
-
if not left_button:
|
|
42
|
-
last_rc_pos = (mx, my)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if left_button:
|
|
46
|
-
camera_context.rotation[0] -= (my - last_rc_pos[1]) * 0.2
|
|
47
|
-
if camera_context.rotation[0] > 180:
|
|
48
|
-
camera_context.rotation[0] = 180
|
|
49
|
-
if camera_context.rotation[0] < 0:
|
|
50
|
-
camera_context.rotation[0] = 0
|
|
51
|
-
smx = (math.sin(math.radians(camera_context.rotation[0]))) + 0.5
|
|
52
|
-
camera_context.rotation[2] -= (mx - last_rc_pos[0]) * 0.2 / smx
|
|
53
|
-
camera_context.position[0] = (math.sin(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
54
|
-
camera_context.position[1] = (math.cos(math.radians(camera_context.rotation[2])) * -cam_dist) * math.sin(math.radians(camera_context.rotation[0]))
|
|
55
|
-
camera_context.position[2] = math.cos(math.radians(camera_context.rotation[0])) * -cam_dist
|
|
56
|
-
last_rc_pos = (mx, my)
|
|
57
|
-
|
|
58
|
-
camera_context.update_screenspace()
|
|
59
|
-
for ro in renderable_objects:
|
|
60
|
-
ro.draw(camera_context)
|
|
61
|
-
|
|
62
|
-
for event in pygame.event.get():
|
|
63
|
-
if event.type == pygame.QUIT:
|
|
64
|
-
done = True
|
|
65
|
-
|
|
66
|
-
pygame.display.flip()
|
|
67
|
-
|
|
68
|
-
exit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|