Formas CSG
Uma caixa mantida em interseção com uma esfera, furada por três cilindros que alternam entre subtração, união e interseção a cada dois segundos.
O editor acima está rodando este projeto. Mude uma linha e ele recarrega.
Classes do Godot usadas
CSGCombiner3DCSGBox3DCSGSphere3DCSGCylinder3D
O código
scripts/main.gd
extends Node
const MODES: Array[Dictionary] = [
{operation = CSGShape3D.OPERATION_SUBTRACTION, label = 'SUBTRACTION'},
{operation = CSGShape3D.OPERATION_UNION, label = 'UNION'},
{operation = CSGShape3D.OPERATION_INTERSECTION, label = 'INTERSECTION'},
]
var bores: Array[CSGShape3D] = []
var caption: Label
var mode: int = 0
func _ready() -> void:
_add_environment()
_add_light()
_build_combiner()
_add_caption()
var camera: Camera3D = Camera3D.new()
camera.position = Vector3(3.2, 2.8, 4.8)
add_child(camera)
camera.look_at(Vector3(0, 0.2, 0), Vector3.UP)
camera.current = true
_cycle()
print('the box keeps its sphere intersection, and the three cylinders change operation every two seconds')
func _cycle() -> void:
while is_inside_tree():
var chosen: Dictionary = MODES[mode]
for bore in bores:
bore.operation = chosen.operation
caption.text = 'cylinders: OPERATION_%s' % chosen.label
mode = (mode + 1) % MODES.size()
await get_tree().create_timer(2.0).timeout
func _build_combiner() -> void:
var combiner: CSGCombiner3D = CSGCombiner3D.new()
combiner.material_override = _make_material('#8da5f3')
add_child(combiner)
var box: CSGBox3D = CSGBox3D.new()
box.size = Vector3(3.4, 3.4, 3.4)
combiner.add_child(box)
var ball: CSGSphere3D = CSGSphere3D.new()
ball.radius = 2.15
ball.radial_segments = 28
ball.rings = 16
ball.operation = CSGShape3D.OPERATION_INTERSECTION
combiner.add_child(ball)
# a CSGCylinder3D grows along its own Y, so each axis needs its own quarter turn
for turn in [Vector3(0, 0, PI * 0.5), Vector3.ZERO, Vector3(PI * 0.5, 0, 0)]:
var bore: CSGCylinder3D = CSGCylinder3D.new()
bore.radius = 0.95
bore.height = 5.2
bore.sides = 24
bore.rotation = turn
combiner.add_child(bore)
bores.append(bore)
func _add_caption() -> void:
var layer: CanvasLayer = CanvasLayer.new()
add_child(layer)
caption = Label.new()
caption.position = Vector2(28, 24)
caption.add_theme_font_size_override('font_size', 26)
caption.add_theme_color_override('font_color', Color('#f3d48d'))
layer.add_child(caption)
func _make_material(hex: String) -> StandardMaterial3D:
var material: StandardMaterial3D = StandardMaterial3D.new()
material.albedo_color = Color(hex)
material.roughness = 0.3
material.metallic = 0.35
return material
func _add_environment() -> void:
var env: Environment = Environment.new()
env.background_mode = Environment.BG_COLOR
env.background_color = Color(0.07, 0.08, 0.13)
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
env.ambient_light_color = Color(0.5, 0.56, 0.74)
env.ambient_light_energy = 0.5
var world: WorldEnvironment = WorldEnvironment.new()
world.environment = env
add_child(world)
func _add_light() -> void:
var key: DirectionalLight3D = DirectionalLight3D.new()
key.rotation_degrees = Vector3(-45, -55, 0)
key.light_energy = 1.6
add_child(key)
var fill: OmniLight3D = OmniLight3D.new()
fill.position = Vector3(-5, 2, 5)
fill.light_color = Color('#fc7f7f')
fill.light_energy = 2.0
fill.omni_range = 22.0
add_child(fill)