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
14 class RenderToTexture
:
16 def __init__(self
, size
=(256, 256)):
17 self
.__set
_buffer
(size
)
18 self
.__set
_display
_region
()
21 self
.display_region
.set_camera(self
.camera
)
23 def __set_buffer(self
, size
):
24 self
.buffer = base
.win
.make_texture_buffer('result buffer', size
[0],
26 self
.buffer.set_sort(-100)
28 def __set_display_region(self
):
29 self
.display_region
= self
.buffer.make_display_region()
30 self
.display_region
.set_sort(20)
32 def __set_camera(self
):
33 self
.camera
= NodePath(Camera('camera 2d'))
34 lens
= OrthographicLens()
35 lens
.set_film_size(1, 1)
36 lens
.set_near_far(-1000, 1000)
37 self
.camera
.node().set_lens(lens
)
40 self
.root
= NodePath('root')
41 self
.root
.set_depth_test(False)
42 self
.root
.set_depth_write(False)
43 self
.camera
.reparent_to(self
.root
)
46 def texture(self
): return self
.buffer.get_texture()
49 base
.graphicsEngine
.remove_window(self
.buffer)
50 if base
.win
: # if you close the window during a race
51 base
.win
.remove_display_region(self
.display_region
)
52 list(map(lambda node
: node
.remove_node(), [self
.camera
, self
.root
]))
57 def __init__(self
, model_path
, antialiasing
, shaders
, srgb
):
58 self
.root
= P3dNode(render
)
62 get_model_path().append_directory(model_path
)
64 root_dir
= LibP3d
.p3dpath(dirname(__file__
))
65 paths
= [root_dir
+ '/' + model_path
, root_dir
]
66 list(map(get_model_path().append_directory
, paths
))
67 render
.set_shader_auto()
68 # render.set_two_sided(True) # it breaks shadows
69 if antialiasing
: render
.set_antialias(AntialiasAttrib
.MAuto
)
70 if shaders
and base
.win
:
71 self
.filters
= CommonFilters(base
.win
, base
.cam
)
73 def load_model(self
, filename
, callback
=None, anim
=None):
74 ext
= '.bam' if exists(filename
+ '.bam') else ''
76 anim_dct
= {'anim': filename
+ '-Anim' + ext
}
77 node
= P3dNode(self
.set_srgb(Actor(filename
+ ext
, anim_dct
)))
79 callb
= lambda model
: callback(P3dNode(self
.set_srgb(model
)))
80 node
= loader
.loadModel(filename
+ ext
, callback
=callb
)
82 node
= P3dNode(self
.set_srgb(
83 loader
.loadModel(LibP3d
.p3dpath(filename
+ ext
))))
86 def set_srgb(self
, model
):
88 for texture
in model
.find_all_textures():
89 if texture
.get_format() in [Texture
.F_rgba
, Texture
.F_rgbm
]:
90 texture
.set_format(Texture
.F_srgb_alpha
)
91 elif texture
.get_format() in [Texture
.F_rgb
]:
92 texture
.set_format(Texture
.F_srgb
)
97 aa_not_none
= render
.get_antialias() != AntialiasAttrib
.MNone
98 if render
.has_antialias() and aa_not_none
:
99 render
.clear_antialias()
100 else: render
.set_antialias(AntialiasAttrib
.MAuto
, 1)
103 tmp_node
= NodePath(PandaNode('temp node'))
104 tmp_node
.set_attrib(LightRampAttrib
.make_single_threshold(.5, .4))
105 tmp_node
.set_shader_auto()
106 base
.cam
.node().set_initial_state(tmp_node
.get_state())
107 self
.filters
.set_cartoon_ink(separation
=1)
110 if not base
.win
: return
111 self
.filters
.setBloom(
112 blend
=(.3, .4, .3, 0), mintrigger
=.6, maxtrigger
=1.0, desat
=.6,
113 intensity
=1.0, size
='medium')
114 # default: (.3, .4, .3, 0), .6, 1, .6, 1, 'medium'
118 p3d
= base
.cam
.get_relative_point(node
.node
, Point3(0, 0, 0))
120 return p2d
if base
.camLens
.project(p3d
, p2d
) else None
123 def screen_coord(pos
):
124 new_node
= NodePath('temp')
125 new_node
.set_pos(pos
)
126 coord3d
= new_node
.get_pos(base
.cam
)
127 new_node
.remove_node()
129 base
.camLens
.project(coord3d
, coord2d
)
130 coord_r2d
= Point3(coord2d
[0], 0, coord2d
[1])
131 coord_a2d
= base
.aspect2d
.get_relative_point(render2d
, coord_r2d
)
132 return coord_a2d
[0], coord_a2d
[2]
135 def world_from_to(pos
):
136 p_from
, p_to
= Point3(), Point3() # in camera coordinates
137 base
.camLens
.extrude(pos
, p_from
, p_to
)
138 p_from
= render
.get_relative_point(base
.cam
, p_from
) # global coords
139 p_to
= render
.get_relative_point(base
.cam
, p_to
) # global coords
143 def shader_support(self
):
144 return base
.win
.get_gsg().get_supports_basic_shaders()
146 def screenshot(self
, path
=None):
147 time
= datetime
.datetime
.now().strftime('%y%m%d%H%M%S')
148 #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
149 #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
150 res
= base
.screenshot(path
or ("yocto%s.png" % time
), False)
151 info('screenshot %s (%s; %s)' % (path
or ("yocto%s.png" % time
), res
, getcwd()))
154 def enable_shader(): render
.set_shader_auto()
157 def disable_shader(): render
.set_shader_off()
160 def print_stats(two_d
=True, three_d
=True, analyze
=True, ls
=True):
161 '''Print graphics stats. They use standard output (from p3d).'''
163 if two_d
and analyze
:
164 info
+=[('render2d.analyze', base
.render2d
.analyze
)]
165 if three_d
and analyze
:
166 info
+=[('render.analyze', base
.render
.analyze
)]
168 info
+=[('render2d.ls', base
.render2d
.ls
)]
170 info
+=[('render.ls', base
.render
.ls
)]
172 print('\n\n#####\n%s()' % elm
[0])
178 def __init__(self
, nodepath
):
179 self
.nodepath
= nodepath
180 self
.node
.set_python_tag('libnode', self
)
182 def set_collide_mask(self
, mask
): return self
.node
.set_collide_mask(mask
)
183 def set_x(self
, val
): return self
.node
.set_x(val
)
184 def set_y(self
, val
): return self
.node
.set_y(val
)
185 def set_z(self
, val
): return self
.node
.set_z(val
)
186 def set_hpr(self
, val
): return self
.node
.set_hpr(val
)
187 def set_h(self
, val
): return self
.node
.set_h(val
)
188 def set_p(self
, val
): return self
.node
.set_p(val
)
189 def set_r(self
, val
): return self
.node
.set_r(val
)
190 def set_scale(self
, val
): return self
.node
.set_scale(val
)
191 def set_transparency(self
, val
): return self
.node
.set_transparency(val
)
192 def set_alpha_scale(self
, val
): return self
.node
.set_alpha_scale(val
)
193 def set_texture(self
, texturestage
, texture
):
194 return self
.node
.set_texture(texturestage
, texture
)
195 def has_tag(self
, name
): return self
.node
.has_tag(name
)
196 def get_tag(self
, name
): return self
.node
.get_tag(name
)
197 def get_python_tag(self
, name
): return self
.node
.get_python_tag(name
)
198 def remove_node(self
): return self
.node
.remove_node()
199 def flatten_strong(self
): return self
.node
.flatten_strong()
200 def clear_model_nodes(self
): return self
.node
.clear_model_nodes()
201 def show(self
): return self
.node
.show()
202 def set_depth_offset(self
, val
): return self
.node
.set_depth_offset(val
)
203 def loop(self
, val
): return self
.node
.loop(val
)
204 def cleanup(self
): return self
.node
.cleanup()
205 def write_bam_file(self
, fname
): return self
.node
.write_bam_file(fname
)
207 def attach_node(self
, name
):
208 return P3dNode(self
.node
.attach_new_node(name
))
210 def add_shape(self
, shape
):
211 return self
.node
.node().add_shape(shape
._mesh
_shape
)
212 #TODO: don't access a protected member
215 def name(self
): return self
.node
.get_name()
218 def node(self
): return self
.nodepath
221 def p3dnode(self
): return self
.node
.node()
223 def set_pos(self
, pos
): return self
.node
.set_pos(pos
._vec
)
224 #TODO: don't access a protected member
226 def get_pos(self
, other
=None):
227 return self
.node
.get_pos(* [] if other
is None else [other
.node
])
230 def x(self
): return self
.node
.get_x()
233 def y(self
): return self
.node
.get_y()
236 def z(self
): return self
.node
.get_z()
239 def hpr(self
): return self
.node
.get_hpr()
242 def h(self
): return self
.node
.get_h()
245 def p(self
): return self
.node
.get_p()
248 def r(self
): return self
.node
.get_r()
251 def scale(self
): return self
.node
.get_scale()
254 def is_empty(self
): return self
.node
.is_empty()
256 def get_relative_vector(self
, node
, vec
):
257 return self
.node
.get_relative_vector(node
.node
, vec
)
259 def set_material(self
, mat
): return self
.node
.set_material(mat
, 1)
261 def set_python_tag(self
, name
, val
):
262 return self
.node
.set_python_tag(name
, val
)
264 def get_distance(self
, other_node
):
265 return self
.node
.get_distance(other_node
.node
)
267 def reparent_to(self
, parent
): return self
.node
.reparent_to(parent
.node
)
269 def wrt_reparent_to(self
, parent
):
270 return self
.node
.wrt_reparent_to(parent
.node
)
273 def __get_pandanode(nodepath
):
274 if nodepath
.has_python_tag('libnode'):
275 return nodepath
.get_python_tag('libnode')
276 return P3dNode(nodepath
)
278 def find_all_matches(self
, name
):
279 nodes
= self
.node
.find_all_matches(name
)
280 return [self
.__get
_pandanode
(node
) for node
in nodes
]
282 def find(self
, name
):
283 model
= self
.node
.find(name
)
284 if model
: return self
.__get
_pandanode
(model
)
287 self
.node
.prepare_scene(base
.win
.get_gsg()) # crash with texture.set_format
288 self
.node
.premunge_scene(base
.win
.get_gsg())
290 def hide(self
, mask
=None):
291 return self
.node
.hide(*[] if mask
is None else [mask
])
294 def tight_bounds(self
): return self
.node
.get_tight_bounds()
297 def parent(self
): return self
.node
.get_parent()
300 def children(self
): return self
.node
.get_children()
302 def destroy(self
): return self
.node
.remove_node()
307 def __init__(self
, filepath
, anim_dct
):
308 self
.node
= Actor(filepath
, anim_dct
)
310 def loop(self
, val
): return self
.node
.loop(val
)
312 def reparent_to(self
, node
): self
.node
.reparent_to(node
)
315 def name(self
): return self
.node
.get_name()
318 self
.node
.prepare_scene(base
.win
.get_gsg())
319 self
.node
.premunge_scene(base
.win
.get_gsg())
322 self
.node
.node().set_bounds(OmniBoundingVolume())
323 self
.node
.node().set_final(True)
325 def destroy(self
): self
.node
.cleanup()
328 class P3dAmbientLight
:
330 def __init__(self
, color
):
331 ambient_lgt
= P3DAmbientLight('ambient light')
332 ambient_lgt
.set_color(color
)
333 self
.ambient_np
= render
.attach_new_node(ambient_lgt
)
334 render
.set_light(self
.ambient_np
)
337 render
.clear_light(self
.ambient_np
)
338 self
.ambient_np
.remove_node()
343 def __init__(self
, mask
=None):
344 self
.spot_lgt
= render
.attach_new_node(P3DSpotlight('spot'))
345 snode
= self
.spot_lgt
.node()
346 snode
.set_scene(render
)
347 snode
.set_shadow_caster(True, 1024, 1024)
348 snode
.get_lens().set_fov(40)
349 snode
.get_lens().set_near_far(20, 200)
350 if mask
: snode
.set_camera_mask(mask
)
351 render
.set_light(self
.spot_lgt
)
353 def set_pos(self
, pos
): return self
.spot_lgt
.set_pos(*pos
)
355 def look_at(self
, pos
): return self
.spot_lgt
.look_at(*pos
)
357 def set_color(self
, color
): return self
.spot_lgt
.set_color(*color
)
360 render
.clear_light(self
.spot_lgt
)
361 self
.spot_lgt
.remove_node()