Commit | Line | Data |
---|---|---|
8ee66edd FC |
1 | import datetime |
2 | from logging import debug, info | |
3 | from os import getcwd | |
4 | from os.path import exists, dirname | |
5 | from panda3d.core import get_model_path, AntialiasAttrib, PandaNode, \ | |
6 | LightRampAttrib, Camera, OrthographicLens, NodePath, OmniBoundingVolume, \ | |
7 | AmbientLight as P3DAmbientLight, Spotlight as P3DSpotlight, Point2, \ | |
8 | Point3, Texture | |
9 | from direct.filter.CommonFilters import CommonFilters | |
10 | from direct.actor.Actor import Actor | |
cb700bcc | 11 | # from ya2.lib.p3d.p3d import LibP3d |
8ee66edd FC |
12 | |
13 | ||
64eae9c7 FC |
14 | def set_srgb(model): |
15 | for texture in model.find_all_textures(): | |
16 | if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]: | |
17 | texture.set_format(Texture.F_srgb_alpha) | |
18 | elif texture.get_format() in [Texture.F_rgb]: | |
19 | texture.set_format(Texture.F_srgb) | |
20 | ||
21 | ||
cb700bcc | 22 | # class RenderToTexture: |
8ee66edd | 23 | |
cb700bcc FC |
24 | # def __init__(self, size=(256, 256)): |
25 | # self.__set_buffer(size) | |
26 | # self.__set_display_region() | |
27 | # self.__set_camera() | |
28 | # self.__set_root() | |
29 | # self.display_region.set_camera(self.camera) | |
8ee66edd | 30 | |
cb700bcc FC |
31 | # def __set_buffer(self, size): |
32 | # self.buffer = base.win.make_texture_buffer('result buffer', size[0], | |
33 | # size[1]) | |
34 | # self.buffer.set_sort(-100) | |
8ee66edd | 35 | |
cb700bcc FC |
36 | # def __set_display_region(self): |
37 | # self.display_region = self.buffer.make_display_region() | |
38 | # self.display_region.set_sort(20) | |
8ee66edd | 39 | |
cb700bcc FC |
40 | # def __set_camera(self): |
41 | # self.camera = NodePath(Camera('camera 2d')) | |
42 | # lens = OrthographicLens() | |
43 | # lens.set_film_size(1, 1) | |
44 | # lens.set_near_far(-1000, 1000) | |
45 | # self.camera.node().set_lens(lens) | |
8ee66edd | 46 | |
cb700bcc FC |
47 | # def __set_root(self): |
48 | # self.root = NodePath('root') | |
49 | # self.root.set_depth_test(False) | |
50 | # self.root.set_depth_write(False) | |
51 | # self.camera.reparent_to(self.root) | |
8ee66edd | 52 | |
cb700bcc FC |
53 | # @property |
54 | # def texture(self): return self.buffer.get_texture() | |
8ee66edd | 55 | |
cb700bcc FC |
56 | # def destroy(self): |
57 | # base.graphicsEngine.remove_window(self.buffer) | |
58 | # if base.win: # if you close the window during a race | |
59 | # base.win.remove_display_region(self.display_region) | |
60 | # list(map(lambda node: node.remove_node(), [self.camera, self.root])) | |
8ee66edd FC |
61 | |
62 | ||
63 | class P3dGfxMgr: | |
64 | ||
65 | def __init__(self, model_path, antialiasing, shaders, srgb): | |
66 | self.root = P3dNode(render) | |
67 | self.__srgb = srgb | |
68 | self.callbacks = {} | |
69 | self.filters = None | |
70 | get_model_path().append_directory(model_path) | |
71 | if LibP3d.runtime(): | |
72 | root_dir = LibP3d.p3dpath(dirname(__file__)) | |
73 | paths = [root_dir + '/' + model_path, root_dir] | |
74 | list(map(get_model_path().append_directory, paths)) | |
75 | render.set_shader_auto() | |
76 | # render.set_two_sided(True) # it breaks shadows | |
77 | if antialiasing: render.set_antialias(AntialiasAttrib.MAuto) | |
78 | if shaders and base.win: | |
79 | self.filters = CommonFilters(base.win, base.cam) | |
80 | ||
81 | def load_model(self, filename, callback=None, anim=None): | |
82 | ext = '.bam' if exists(filename + '.bam') else '' | |
83 | if anim: | |
84 | anim_dct = {'anim': filename + '-Anim' + ext} | |
85 | node = P3dNode(self.set_srgb(Actor(filename + ext, anim_dct))) | |
86 | elif callback: | |
87 | callb = lambda model: callback(P3dNode(self.set_srgb(model))) | |
88 | node = loader.loadModel(filename + ext, callback=callb) | |
89 | else: | |
90 | node = P3dNode(self.set_srgb( | |
91 | loader.loadModel(LibP3d.p3dpath(filename + ext)))) | |
92 | return node | |
93 | ||
94 | def set_srgb(self, model): | |
95 | if self.__srgb: | |
96 | for texture in model.find_all_textures(): | |
97 | if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]: | |
98 | texture.set_format(Texture.F_srgb_alpha) | |
99 | elif texture.get_format() in [Texture.F_rgb]: | |
100 | texture.set_format(Texture.F_srgb) | |
101 | return model | |
102 | ||
103 | @staticmethod | |
104 | def toggle_aa(): | |
105 | aa_not_none = render.get_antialias() != AntialiasAttrib.MNone | |
106 | if render.has_antialias() and aa_not_none: | |
107 | render.clear_antialias() | |
108 | else: render.set_antialias(AntialiasAttrib.MAuto, 1) | |
109 | ||
110 | def set_toon(self): | |
111 | tmp_node = NodePath(PandaNode('temp node')) | |
112 | tmp_node.set_attrib(LightRampAttrib.make_single_threshold(.5, .4)) | |
113 | tmp_node.set_shader_auto() | |
114 | base.cam.node().set_initial_state(tmp_node.get_state()) | |
115 | self.filters.set_cartoon_ink(separation=1) | |
116 | ||
117 | def set_bloom(self): | |
118 | if not base.win: return | |
119 | self.filters.setBloom( | |
120 | blend=(.3, .4, .3, 0), mintrigger=.6, maxtrigger=1.0, desat=.6, | |
121 | intensity=1.0, size='medium') | |
122 | # default: (.3, .4, .3, 0), .6, 1, .6, 1, 'medium' | |
123 | ||
124 | @staticmethod | |
125 | def pos2d(node): | |
126 | p3d = base.cam.get_relative_point(node.node, Point3(0, 0, 0)) | |
127 | p2d = Point2() | |
128 | return p2d if base.camLens.project(p3d, p2d) else None | |
129 | ||
13263131 FC |
130 | @staticmethod |
131 | def screen_coord(pos): | |
132 | new_node = NodePath('temp') | |
133 | new_node.set_pos(pos) | |
134 | coord3d = new_node.get_pos(base.cam) | |
135 | new_node.remove_node() | |
136 | coord2d = Point2() | |
137 | base.camLens.project(coord3d, coord2d) | |
138 | coord_r2d = Point3(coord2d[0], 0, coord2d[1]) | |
139 | coord_a2d = base.aspect2d.get_relative_point(render2d, coord_r2d) | |
140 | return coord_a2d[0], coord_a2d[2] | |
141 | ||
142 | @staticmethod | |
143 | def world_from_to(pos): | |
144 | p_from, p_to = Point3(), Point3() # in camera coordinates | |
145 | base.camLens.extrude(pos, p_from, p_to) | |
146 | p_from = render.get_relative_point(base.cam, p_from) # global coords | |
147 | p_to = render.get_relative_point(base.cam, p_to) # global coords | |
148 | return p_from, p_to | |
149 | ||
8ee66edd FC |
150 | @property |
151 | def shader_support(self): | |
152 | return base.win.get_gsg().get_supports_basic_shaders() | |
153 | ||
154 | def screenshot(self, path=None): | |
155 | time = datetime.datetime.now().strftime('%y%m%d%H%M%S') | |
156 | #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time))) | |
157 | #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res)) | |
8ce16d6c FC |
158 | res = base.screenshot(path or ("pmachines%s.png" % time), False) |
159 | info('screenshot %s (%s; %s)' % (path or ("pmachines%s.png" % time), res, getcwd())) | |
8ee66edd FC |
160 | |
161 | @staticmethod | |
162 | def enable_shader(): render.set_shader_auto() | |
163 | ||
164 | @staticmethod | |
165 | def disable_shader(): render.set_shader_off() | |
166 | ||
167 | @staticmethod | |
168 | def print_stats(two_d=True, three_d=True, analyze=True, ls=True): | |
169 | '''Print graphics stats. They use standard output (from p3d).''' | |
170 | info = [] | |
171 | if two_d and analyze: | |
172 | info +=[('render2d.analyze', base.render2d.analyze)] | |
173 | if three_d and analyze: | |
174 | info +=[('render.analyze', base.render.analyze)] | |
175 | if two_d and ls: | |
176 | info +=[('render2d.ls', base.render2d.ls)] | |
177 | if three_d and ls: | |
178 | info +=[('render.ls', base.render.ls)] | |
179 | for elm in info: | |
180 | print('\n\n#####\n%s()' % elm[0]) | |
181 | elm[1]() | |
182 | ||
183 | ||
cb700bcc | 184 | # class P3dNode: |
8ee66edd | 185 | |
cb700bcc FC |
186 | # def __init__(self, nodepath): |
187 | # self.nodepath = nodepath | |
188 | # self.node.set_python_tag('libnode', self) | |
8ee66edd | 189 | |
cb700bcc FC |
190 | # def set_collide_mask(self, mask): return self.node.set_collide_mask(mask) |
191 | # def set_x(self, val): return self.node.set_x(val) | |
192 | # def set_y(self, val): return self.node.set_y(val) | |
193 | # def set_z(self, val): return self.node.set_z(val) | |
194 | # def set_hpr(self, val): return self.node.set_hpr(val) | |
195 | # def set_h(self, val): return self.node.set_h(val) | |
196 | # def set_p(self, val): return self.node.set_p(val) | |
197 | # def set_r(self, val): return self.node.set_r(val) | |
198 | # def set_scale(self, val): return self.node.set_scale(val) | |
199 | # def set_transparency(self, val): return self.node.set_transparency(val) | |
200 | # def set_alpha_scale(self, val): return self.node.set_alpha_scale(val) | |
201 | # def set_texture(self, texturestage, texture): | |
202 | # return self.node.set_texture(texturestage, texture) | |
203 | # def has_tag(self, name): return self.node.has_tag(name) | |
204 | # def get_tag(self, name): return self.node.get_tag(name) | |
205 | # def get_python_tag(self, name): return self.node.get_python_tag(name) | |
206 | # def remove_node(self): return self.node.remove_node() | |
207 | # def flatten_strong(self): return self.node.flatten_strong() | |
208 | # def clear_model_nodes(self): return self.node.clear_model_nodes() | |
209 | # def show(self): return self.node.show() | |
210 | # def set_depth_offset(self, val): return self.node.set_depth_offset(val) | |
211 | # def loop(self, val): return self.node.loop(val) | |
212 | # def cleanup(self): return self.node.cleanup() | |
213 | # def write_bam_file(self, fname): return self.node.write_bam_file(fname) | |
8ee66edd | 214 | |
cb700bcc FC |
215 | # def attach_node(self, name): |
216 | # return P3dNode(self.node.attach_new_node(name)) | |
8ee66edd | 217 | |
cb700bcc FC |
218 | # def add_shape(self, shape): |
219 | # return self.node.node().add_shape(shape._mesh_shape) | |
220 | # #TODO: don't access a protected member | |
8ee66edd | 221 | |
cb700bcc FC |
222 | # @property |
223 | # def name(self): return self.node.get_name() | |
8ee66edd | 224 | |
cb700bcc FC |
225 | # @property |
226 | # def node(self): return self.nodepath | |
8ee66edd | 227 | |
cb700bcc FC |
228 | # @property |
229 | # def p3dnode(self): return self.node.node() | |
8ee66edd | 230 | |
cb700bcc FC |
231 | # def set_pos(self, pos): return self.node.set_pos(pos._vec) |
232 | # #TODO: don't access a protected member | |
8ee66edd | 233 | |
cb700bcc FC |
234 | # def get_pos(self, other=None): |
235 | # return self.node.get_pos(* [] if other is None else [other.node]) | |
8ee66edd | 236 | |
cb700bcc FC |
237 | # @property |
238 | # def x(self): return self.node.get_x() | |
8ee66edd | 239 | |
cb700bcc FC |
240 | # @property |
241 | # def y(self): return self.node.get_y() | |
8ee66edd | 242 | |
cb700bcc FC |
243 | # @property |
244 | # def z(self): return self.node.get_z() | |
8ee66edd | 245 | |
cb700bcc FC |
246 | # @property |
247 | # def hpr(self): return self.node.get_hpr() | |
8ee66edd | 248 | |
cb700bcc FC |
249 | # @property |
250 | # def h(self): return self.node.get_h() | |
8ee66edd | 251 | |
cb700bcc FC |
252 | # @property |
253 | # def p(self): return self.node.get_p() | |
8ee66edd | 254 | |
cb700bcc FC |
255 | # @property |
256 | # def r(self): return self.node.get_r() | |
8ee66edd | 257 | |
cb700bcc FC |
258 | # @property |
259 | # def scale(self): return self.node.get_scale() | |
8ee66edd | 260 | |
cb700bcc FC |
261 | # @property |
262 | # def is_empty(self): return self.node.is_empty() | |
8ee66edd | 263 | |
cb700bcc FC |
264 | # def get_relative_vector(self, node, vec): |
265 | # return self.node.get_relative_vector(node.node, vec) | |
8ee66edd | 266 | |
cb700bcc | 267 | # def set_material(self, mat): return self.node.set_material(mat, 1) |
8ee66edd | 268 | |
cb700bcc FC |
269 | # def set_python_tag(self, name, val): |
270 | # return self.node.set_python_tag(name, val) | |
8ee66edd | 271 | |
cb700bcc FC |
272 | # def get_distance(self, other_node): |
273 | # return self.node.get_distance(other_node.node) | |
8ee66edd | 274 | |
cb700bcc | 275 | # def reparent_to(self, parent): return self.node.reparent_to(parent.node) |
8ee66edd | 276 | |
cb700bcc FC |
277 | # def wrt_reparent_to(self, parent): |
278 | # return self.node.wrt_reparent_to(parent.node) | |
8ee66edd | 279 | |
cb700bcc FC |
280 | # @staticmethod |
281 | # def __get_pandanode(nodepath): | |
282 | # if nodepath.has_python_tag('libnode'): | |
283 | # return nodepath.get_python_tag('libnode') | |
284 | # return P3dNode(nodepath) | |
8ee66edd | 285 | |
cb700bcc FC |
286 | # def find_all_matches(self, name): |
287 | # nodes = self.node.find_all_matches(name) | |
288 | # return [self.__get_pandanode(node) for node in nodes] | |
8ee66edd | 289 | |
cb700bcc FC |
290 | # def find(self, name): |
291 | # model = self.node.find(name) | |
292 | # if model: return self.__get_pandanode(model) | |
8ee66edd | 293 | |
cb700bcc FC |
294 | # def optimize(self): |
295 | # self.node.prepare_scene(base.win.get_gsg()) # crash with texture.set_format | |
296 | # self.node.premunge_scene(base.win.get_gsg()) | |
8ee66edd | 297 | |
cb700bcc FC |
298 | # def hide(self, mask=None): |
299 | # return self.node.hide(*[] if mask is None else [mask]) | |
8ee66edd | 300 | |
cb700bcc FC |
301 | # @property |
302 | # def tight_bounds(self): return self.node.get_tight_bounds() | |
8ee66edd | 303 | |
cb700bcc FC |
304 | # @property |
305 | # def parent(self): return self.node.get_parent() | |
8ee66edd | 306 | |
cb700bcc FC |
307 | # @property |
308 | # def children(self): return self.node.get_children() | |
8ee66edd | 309 | |
cb700bcc | 310 | # def destroy(self): return self.node.remove_node() |
8ee66edd | 311 | |
8ee66edd | 312 | |
cb700bcc FC |
313 | # class P3dAnimNode: |
314 | ||
315 | # def __init__(self, filepath, anim_dct): | |
316 | # self.node = Actor(filepath, anim_dct) | |
317 | ||
318 | # def loop(self, val): return self.node.loop(val) | |
319 | ||
320 | # def reparent_to(self, node): self.node.reparent_to(node) | |
321 | ||
322 | # @property | |
323 | # def name(self): return self.node.get_name() | |
8ee66edd | 324 | |
cb700bcc FC |
325 | # def optimize(self): |
326 | # self.node.prepare_scene(base.win.get_gsg()) | |
327 | # self.node.premunge_scene(base.win.get_gsg()) | |
8ee66edd | 328 | |
cb700bcc FC |
329 | # def set_omni(self): |
330 | # self.node.node().set_bounds(OmniBoundingVolume()) | |
331 | # self.node.node().set_final(True) | |
8ee66edd | 332 | |
cb700bcc | 333 | # def destroy(self): self.node.cleanup() |
8ee66edd FC |
334 | |
335 | ||
cb700bcc | 336 | # class P3dAmbientLight: |
8ee66edd | 337 | |
cb700bcc FC |
338 | # def __init__(self, color): |
339 | # ambient_lgt = P3DAmbientLight('ambient light') | |
340 | # ambient_lgt.set_color(color) | |
341 | # self.ambient_np = render.attach_new_node(ambient_lgt) | |
342 | # render.set_light(self.ambient_np) | |
8ee66edd | 343 | |
cb700bcc FC |
344 | # def destroy(self): |
345 | # render.clear_light(self.ambient_np) | |
346 | # self.ambient_np.remove_node() | |
8ee66edd FC |
347 | |
348 | ||
cb700bcc | 349 | # class P3dSpotlight: |
8ee66edd | 350 | |
cb700bcc FC |
351 | # def __init__(self, mask=None): |
352 | # self.spot_lgt = render.attach_new_node(P3DSpotlight('spot')) | |
353 | # snode = self.spot_lgt.node() | |
354 | # snode.set_scene(render) | |
355 | # snode.set_shadow_caster(True, 1024, 1024) | |
356 | # snode.get_lens().set_fov(40) | |
357 | # snode.get_lens().set_near_far(20, 200) | |
358 | # if mask: snode.set_camera_mask(mask) | |
359 | # render.set_light(self.spot_lgt) | |
8ee66edd | 360 | |
cb700bcc | 361 | # def set_pos(self, pos): return self.spot_lgt.set_pos(*pos) |
8ee66edd | 362 | |
cb700bcc | 363 | # def look_at(self, pos): return self.spot_lgt.look_at(*pos) |
8ee66edd | 364 | |
cb700bcc | 365 | # def set_color(self, color): return self.spot_lgt.set_color(*color) |
8ee66edd | 366 | |
cb700bcc FC |
367 | # def destroy(self): |
368 | # render.clear_light(self.spot_lgt) | |
369 | # self.spot_lgt.remove_node() |