073740cea38e406432521287c791b6bc62a22f42
2 from logging
import debug
, info
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
, \
9 from direct
.filter.CommonFilters
import CommonFilters
10 from direct
.actor
.Actor
import Actor
11 from lib
.lib
.p3d
.p3d
import LibP3d
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
)
22 class RenderToTexture
:
24 def __init__(self
, size
=(256, 256)):
25 self
.__set
_buffer
(size
)
26 self
.__set
_display
_region
()
29 self
.display_region
.set_camera(self
.camera
)
31 def __set_buffer(self
, size
):
32 self
.buffer = base
.win
.make_texture_buffer('result buffer', size
[0],
34 self
.buffer.set_sort(-100)
36 def __set_display_region(self
):
37 self
.display_region
= self
.buffer.make_display_region()
38 self
.display_region
.set_sort(20)
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
)
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
)
54 def texture(self
): return self
.buffer.get_texture()
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
]))
65 def __init__(self
, model_path
, antialiasing
, shaders
, srgb
):
66 self
.root
= P3dNode(render
)
70 get_model_path().append_directory(model_path
)
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
)
81 def load_model(self
, filename
, callback
=None, anim
=None):
82 ext
= '.bam' if exists(filename
+ '.bam') else ''
84 anim_dct
= {'anim': filename
+ '-Anim' + ext
}
85 node
= P3dNode(self
.set_srgb(Actor(filename
+ ext
, anim_dct
)))
87 callb
= lambda model
: callback(P3dNode(self
.set_srgb(model
)))
88 node
= loader
.loadModel(filename
+ ext
, callback
=callb
)
90 node
= P3dNode(self
.set_srgb(
91 loader
.loadModel(LibP3d
.p3dpath(filename
+ ext
))))
94 def set_srgb(self
, model
):
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
)
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)
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)
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'
126 p3d
= base
.cam
.get_relative_point(node
.node
, Point3(0, 0, 0))
128 return p2d
if base
.camLens
.project(p3d
, p2d
) else None
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()
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]
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
151 def shader_support(self
):
152 return base
.win
.get_gsg().get_supports_basic_shaders()
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))
158 res
= base
.screenshot(path
or ("yocto%s.png" % time
), False)
159 info('screenshot %s (%s; %s)' % (path
or ("yocto%s.png" % time
), res
, getcwd()))
162 def enable_shader(): render
.set_shader_auto()
165 def disable_shader(): render
.set_shader_off()
168 def print_stats(two_d
=True, three_d
=True, analyze
=True, ls
=True):
169 '''Print graphics stats. They use standard output (from p3d).'''
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
)]
176 info
+=[('render2d.ls', base
.render2d
.ls
)]
178 info
+=[('render.ls', base
.render
.ls
)]
180 print('\n\n#####\n%s()' % elm
[0])
186 def __init__(self
, nodepath
):
187 self
.nodepath
= nodepath
188 self
.node
.set_python_tag('libnode', self
)
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
)
215 def attach_node(self
, name
):
216 return P3dNode(self
.node
.attach_new_node(name
))
218 def add_shape(self
, shape
):
219 return self
.node
.node().add_shape(shape
._mesh
_shape
)
220 #TODO: don't access a protected member
223 def name(self
): return self
.node
.get_name()
226 def node(self
): return self
.nodepath
229 def p3dnode(self
): return self
.node
.node()
231 def set_pos(self
, pos
): return self
.node
.set_pos(pos
._vec
)
232 #TODO: don't access a protected member
234 def get_pos(self
, other
=None):
235 return self
.node
.get_pos(* [] if other
is None else [other
.node
])
238 def x(self
): return self
.node
.get_x()
241 def y(self
): return self
.node
.get_y()
244 def z(self
): return self
.node
.get_z()
247 def hpr(self
): return self
.node
.get_hpr()
250 def h(self
): return self
.node
.get_h()
253 def p(self
): return self
.node
.get_p()
256 def r(self
): return self
.node
.get_r()
259 def scale(self
): return self
.node
.get_scale()
262 def is_empty(self
): return self
.node
.is_empty()
264 def get_relative_vector(self
, node
, vec
):
265 return self
.node
.get_relative_vector(node
.node
, vec
)
267 def set_material(self
, mat
): return self
.node
.set_material(mat
, 1)
269 def set_python_tag(self
, name
, val
):
270 return self
.node
.set_python_tag(name
, val
)
272 def get_distance(self
, other_node
):
273 return self
.node
.get_distance(other_node
.node
)
275 def reparent_to(self
, parent
): return self
.node
.reparent_to(parent
.node
)
277 def wrt_reparent_to(self
, parent
):
278 return self
.node
.wrt_reparent_to(parent
.node
)
281 def __get_pandanode(nodepath
):
282 if nodepath
.has_python_tag('libnode'):
283 return nodepath
.get_python_tag('libnode')
284 return P3dNode(nodepath
)
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
]
290 def find(self
, name
):
291 model
= self
.node
.find(name
)
292 if model
: return self
.__get
_pandanode
(model
)
295 self
.node
.prepare_scene(base
.win
.get_gsg()) # crash with texture.set_format
296 self
.node
.premunge_scene(base
.win
.get_gsg())
298 def hide(self
, mask
=None):
299 return self
.node
.hide(*[] if mask
is None else [mask
])
302 def tight_bounds(self
): return self
.node
.get_tight_bounds()
305 def parent(self
): return self
.node
.get_parent()
308 def children(self
): return self
.node
.get_children()
310 def destroy(self
): return self
.node
.remove_node()
315 def __init__(self
, filepath
, anim_dct
):
316 self
.node
= Actor(filepath
, anim_dct
)
318 def loop(self
, val
): return self
.node
.loop(val
)
320 def reparent_to(self
, node
): self
.node
.reparent_to(node
)
323 def name(self
): return self
.node
.get_name()
326 self
.node
.prepare_scene(base
.win
.get_gsg())
327 self
.node
.premunge_scene(base
.win
.get_gsg())
330 self
.node
.node().set_bounds(OmniBoundingVolume())
331 self
.node
.node().set_final(True)
333 def destroy(self
): self
.node
.cleanup()
336 class P3dAmbientLight
:
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
)
345 render
.clear_light(self
.ambient_np
)
346 self
.ambient_np
.remove_node()
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
)
361 def set_pos(self
, pos
): return self
.spot_lgt
.set_pos(*pos
)
363 def look_at(self
, pos
): return self
.spot_lgt
.look_at(*pos
)
365 def set_color(self
, color
): return self
.spot_lgt
.set_color(*color
)
368 render
.clear_light(self
.spot_lgt
)
369 self
.spot_lgt
.remove_node()