3DCoat Python API
The 3DCoat Python API documentation.
Loading...
Searching...
No Matches
render_with_shadow.py

Render object from the random top view with random light position.

Render object from the random top view with random light position. The object rendered as if it drops the shadow on the invisible plane. The shadow represented as the alpha channel of the final image.

1# this examle takes the mesh from the paint or sculpt room, renders from above (a bit random direction, random light) and saves the rendered image to the
2# specified path. This example demonstrates the camera manipulation and rendering.
3# The object rendered as if it drops the shadow on the invisible plane.
4# The shadow represented as the alpha channel of the final image.
5
6from coat import *
7import random
8
9# the scene scale and shift, we need to create the correct render background
10ssc = Scene.GetSceneScale()
11shift = Scene.getSceneShift()
12
13# the mesh from the paint room
14m = Mesh()
15m.fromPaintRoom()
16m.transform(mat4.Translation(vec3(0, - shift.y * ssc,0)))
17
18bb = m.getBounds()
19# we need to scale bound box to get it in scene (nt world) units because sculpt objects measured in scene units as well
20# but exported mesh is in world units
21bb = boundbox.Transform(bb, mat4.Scaling(ssc))
22
23# remove any existing background, calculate boundbox of sculpt objects in scene, if any
24def removebg(x):
25 if x.name() == "bg_round":
26 x.clear()
27 x.remove()
28 else:
29 bb.AddBounds(x.Volume().calcWorldSpaceAABB())
30 return False
31def removeBgObject():
32 for i in range(2) : Scene.sculptRoot().iterateVisibleSubtree(removebg)
33
34# remove any existing background
35removeBgObject()
36
37if(bb.IsEmpty()):
38 dialog.text("The scene is empty").ok().show()
39 exit(1)
40
41bottom = bb.GetMin().y
42m1 = bb.GetMin()
43m2 = bb.GetMax()
44# we set y to zero because we need object size from the above, so we measure diagonal from the above
45m1.y = m2.y = 0
46radius = m1.distance(m2) * 2
47
48cyl = Mesh.cylinder(vec3(0,bottom - radius/20,0), radius, radius/10,0,16,128,128,0)
49
50v=Volume()
51# create background object
52v = Scene.sculptRoot().addChild("bg_round").Volume()
53v.toSurface()
54cyl.toVolume(v)
55# set the simplest possible flat shader for the background object
56v.setBoolShaderProperty("UseColorTexture", False)
57v.setBoolShaderProperty("UseGlossTexture", False)
58v.setBoolShaderProperty("UseMetalnessTexture", False)
59v.setBoolShaderProperty("UseNormalmapTexture", False)
60v.setBoolShaderProperty("UseCavity", False)
61v.setBoolShaderProperty("FlatShading", False)
62v.setFloatShaderProperty("Gloss",0)
63v.setFloatShaderProperty("Metalness",0)
64
65RenderRoom.toRenderRoom()
66
67base = io.currentSceneFilepath()
68# get the file name without extension and full path
69base = io.getFileName(base)
70base = base[:base.rfind(".")]
71
72#setup the render room, we take 512*512 images with 256 rays per frame
73RenderRoom.setCustomRenderSize(512, 512)
74RenderRoom.setRaysPerFrame(256)
75height = io.workArea().GetHeight()
76
77# we need just N frames to render
78N = 4
79for j in range(0, N):
80 #setup the random light, random ambient light and random camera position (from above)
81 value = random.random() * 0.5
82 RenderRoom.removeAllLights()
83 RenderRoom.addLight()
84 RenderRoom.setEnvironmentLight(100 - value * 50)
85 ldir = vec3.RandNormal()
86 ldir += vec3.AxisY*2
87 ldir.Normalize()
88 RenderRoom.setLightDirection(0, ldir)
89 RenderRoom.setLightColor(0)
90 RenderRoom.setLightIntensity(0, value)
91 RenderRoom.setLightScattering(0,0.1)
92
93 # the direction from above with a bit random horizontal shift
94 start = vec3.RandNormal() + vec3.AxisY*3
95 start.Normalize()
96 # distant anough to fit the object into the square image
97 start *= radius*4*height/2000
98 # FOV is 50 degrees
99 Camera.setCamera(start, vec3(0,0,0), 50)
100
101 # look the progress in the header
102 io.progressBarInWindowHeader(j, N-1, "Rendering")
103
104 # render the frame on the RED background
105 v.setColorShaderProperty("Color",0xFFFF0000)
106 RenderRoom.setRenderResult(f"UserPrefs/render/red.png")
107 RenderRoom.renderFrame()
108
109 # the GREEN background
110 v.setColorShaderProperty("Color",0xFF00FF00)
111 RenderRoom.setRenderResult(f"UserPrefs/render/green.png")
112 RenderRoom.renderFrame()
113
114 # we use 2 images with red and green background to remove the background and the the alpha channel (incliding shadow ovwr the invisible plane)
115 io.removeBackground(f"UserPrefs/render/red.png",f"UserPrefs/render/green.png",f"UserPrefs/render/result/{base}/{j:04d}.png")
116 io.removeFile(f"UserPrefs/render/red.png")
117 io.removeFile(f"UserPrefs/render/green.png")
118
119io.exec(io.documents("UserPrefs/render/result/"))
120removeBgObject()