Formes CSG

Une boîte gardée en intersection avec une sphère, percée par trois cylindres qui alternent entre soustraction, union et intersection toutes les deux secondes.

L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.

Classes Godot utilisées

CSGCombiner3DCSGBox3DCSGSphere3DCSGCylinder3D

Le code

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)

Plus d'exemples de Scène 3D