#version 3.7; /* Animated Marionette Puppets performing in a Medieval Castle Courtyard. Tip: Render an animation with clock from 0 to 1 for a seamless loop. */ global_settings { assumed_gamma 1.3 max_trace_level 16 radiosity { pretrace_start 0.08 pretrace_end 0.01 count 200 nearest_count 10 error_bound 0.5 recursion_limit 2 low_error_factor 0.5 gray_threshold 0.0 } } background { color rgb <0.93, 0.95, 0.98> } camera { location <12.5, 6.4, -15.8> look_at <0.0, 2.3, 4.2> angle 40 up <0,9,0> right <16,0,0> // right,up -> 16:9 } // ---------------- Lights (warm, soft shadows) ---------------- light_source { <18, 16, -18> color rgb <1.00, 0.86, 0.70>*1.10 area_light <3.2,0,0>, <0,0,3.2>, 6, 6 adaptive 1 jitter } light_source { <-16, 11, -6> color rgb <1.00, 0.90, 0.80>*0.55 area_light <2.6,0,0>, <0,0,2.6>, 5, 5 adaptive 1 jitter } light_source { <0, 14, 10> color rgb <1.00, 0.88, 0.76>*0.35 area_light <3.0,0,0>, <0,0,3.0>, 5, 5 adaptive 1 jitter } // subtle torch accents near gate light_source { <-1.6, 2.8, 0.65> color rgb <1.0,0.62,0.28>*0.35 fade_distance 5 fade_power 2 area_light <0.6,0,0>, <0,0.6,0>, 4, 4 adaptive 1 jitter } light_source { < 1.6, 2.8, 0.65> color rgb <1.0,0.62,0.28>*0.35 fade_distance 5 fade_power 2 area_light <0.6,0,0>, <0,0.6,0>, 4, 4 adaptive 1 jitter } // ---------------- Textures (procedural, fast; fixed warp-repeat error) ---------------- #declare Tex_StoneBlocks = texture{ pigment{ granite color_map{ [0.00 color rgb <0.47,0.49,0.52>] [0.45 color rgb <0.70,0.72,0.75>] [1.00 color rgb <0.84,0.86,0.88>] } scale <0.60,0.38,0.60> } normal { bumps 0.50 scale 0.18 } finish { diffuse 0.90 specular 0.06 roughness 0.16 } } #declare Tex_StonePlinth = texture{ pigment{ granite color_map{ [0.00 color rgb <0.42,0.43,0.45>] [0.55 color rgb <0.62,0.64,0.67>] [1.00 color rgb <0.78,0.80,0.82>] } scale <0.45,0.30,0.45> } normal { bumps 0.60 scale 0.16 } finish { diffuse 0.90 specular 0.05 roughness 0.18 } } #declare Tex_GroundCourtyard = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.58,0.60,0.62>] [0.45 color rgb <0.75,0.77,0.79>] [1.00 color rgb <0.88,0.90,0.92>] } scale 2.2 turbulence 0.35 } normal{ average normal_map{ [0.55 bumps 0.40 scale 0.22] [0.45 wrinkles 0.20 scale 0.90] } } finish { diffuse 0.92 specular 0.03 roughness 0.18 } } #declare Tex_Wood = texture{ pigment{ wood color_map{ [0.00 color rgb <0.20,0.13,0.08>] [0.35 color rgb <0.38,0.24,0.15>] [0.75 color rgb <0.56,0.36,0.22>] [1.00 color rgb <0.28,0.18,0.11>] } turbulence 0.12 scale <0.24,0.24,2.6> rotate <0,90,0> } normal { wood 0.55 scale 0.20 rotate <0,90,0> } finish { diffuse 0.85 specular 0.08 roughness 0.12 } } #declare Tex_Rope = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.54,0.47,0.32>] [0.55 color rgb <0.78,0.70,0.52>] [1.00 color rgb <0.88,0.82,0.66>] } scale 0.40 turbulence 0.25 } normal{ average normal_map{ [0.70 bumps 0.60 scale <0.06,0.06,0.25> rotate <0,0,35>] [0.30 bumps 0.40 scale <0.06,0.06,0.25> rotate <0,0,-35>] } } finish { diffuse 0.90 specular 0.04 roughness 0.22 } } #declare Tex_ClothBlue = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.10,0.20,0.50>] [0.55 color rgb <0.22,0.42,0.85>] [1.00 color rgb <0.12,0.28,0.66>] } scale 0.30 turbulence 0.20 } normal { bumps 0.35 scale 0.08 } finish { diffuse 0.90 specular 0.06 roughness 0.11 } } #declare Tex_ClothRed = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.52,0.09,0.09>] [0.55 color rgb <0.86,0.22,0.20>] [1.00 color rgb <0.70,0.14,0.14>] } scale 0.30 turbulence 0.20 } normal { bumps 0.35 scale 0.08 } finish { diffuse 0.90 specular 0.06 roughness 0.11 } } #declare Tex_ClothGreen = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.10,0.28,0.17>] [0.55 color rgb <0.20,0.65,0.38>] [1.00 color rgb <0.14,0.48,0.28>] } scale 0.30 turbulence 0.20 } normal { bumps 0.35 scale 0.08 } finish { diffuse 0.90 specular 0.06 roughness 0.11 } } #declare Tex_Skin = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.76,0.60,0.50>] [0.55 color rgb <0.88,0.74,0.60>] [1.00 color rgb <0.95,0.84,0.72>] } scale 0.22 turbulence 0.25 } normal { bumps 0.22 scale 0.06 } finish { diffuse 0.90 specular 0.10 roughness 0.07 } } #declare Tex_Metal = texture{ pigment{ color rgb <0.38,0.39,0.41> } normal { bumps 0.18 scale 0.05 } finish { diffuse 0.35 specular 0.55 roughness 0.03 } } #declare Tex_DarkPassage = texture{ pigment{ bozo color_map{ [0.00 color rgb <0.06,0.06,0.08>] [1.00 color rgb <0.22,0.23,0.25>] } scale 1.0 } finish { diffuse 0.95 specular 0.02 roughness 0.35 } } // Slightly different stone for accents (gatehouse/arch feel) #declare Tex_StoneAccent = texture{ pigment{ granite color_map{ [0.00 color rgb <0.40,0.42,0.45>] [0.55 color rgb <0.63,0.65,0.68>] [1.00 color rgb <0.80,0.82,0.84>] } scale <0.50,0.32,0.50> } normal { bumps 0.55 scale 0.16 } finish { diffuse 0.90 specular 0.06 roughness 0.16 } } // ---------- Helpers ---------- #declare TAU = 6.28318530718; #declare T = clock; #declare Sway = sin(T*TAU); #macro CrenelatedTop(LengthX, TopY, ZCenter, WallThick, CrenW, CrenH, Phase) union { #local StartX = -LengthX/2; #local EndX = LengthX/2; #local X = StartX; #while (X < EndX - 0.0001) #local isUp = (mod(floor((X-StartX)/CrenW + Phase), 2) = 0); #if (isUp) box { , } #end #local X = X + CrenW; #end } #end #macro TowerCrenels(R, TopY, CrenW, CrenH, N) union { #local i=0; #while (i, rotate <0, degrees(ang), 0> } #end #local i=i+1; #end } #end // ---------- Courtyard ground ---------- plane { y, 0 texture { Tex_GroundCourtyard } } // ---------- Castle (simple medieval layout) ---------- #declare CourtyardZ = 7.3; #declare WallHeight = 4.3; #declare WallThick = 1.10; #declare WallTopY = WallHeight; #declare CrenW = 0.70; #declare CrenH = 0.70; #declare CastleHalfX = 8.7; #declare CastleHalfZ = 6.6; #declare Wall_Front = box { <-CastleHalfX,0,CourtyardZ-CastleHalfZ>, < CastleHalfX,WallHeight,CourtyardZ-CastleHalfZ+WallThick> } #declare Wall_Back = box { <-CastleHalfX,0,CourtyardZ+CastleHalfZ-WallThick>, < CastleHalfX,WallHeight,CourtyardZ+CastleHalfZ> } #declare Wall_Left = box { <-CastleHalfX,0,CourtyardZ-CastleHalfZ>, <-CastleHalfX+WallThick,WallHeight,CourtyardZ+CastleHalfZ> } #declare Wall_Right = box { < CastleHalfX-WallThick,0,CourtyardZ-CastleHalfZ>, < CastleHalfX,WallHeight,CourtyardZ+CastleHalfZ> } // Gatehouse (front-center) #declare GateW = 3.0; #declare GateH = 3.1; #declare GatehouseW = 4.6; #declare GatehouseD = 2.2; #declare GatehouseH = 5.4; #declare Gatehouse = difference { box { <-GatehouseW/2, 0, CourtyardZ-CastleHalfZ-0.0001>, < GatehouseW/2, GatehouseH, CourtyardZ-CastleHalfZ+GatehouseD> } box { // door opening <-GateW/2, 0, CourtyardZ-CastleHalfZ-0.25>, < GateW/2, GateH, CourtyardZ-CastleHalfZ+GatehouseD+0.25> } } // Corner towers placed so they "sit into" the wall footprint cleanly #declare TowerR = 1.60; #declare TowerH = 6.4; #declare Tower_Pos1 = < CastleHalfX-WallThick, 0, CourtyardZ-CastleHalfZ+WallThick>; #declare Tower_Pos2 = <-CastleHalfX+WallThick, 0, CourtyardZ-CastleHalfZ+WallThick>; #declare Tower_Pos3 = < CastleHalfX-WallThick, 0, CourtyardZ+CastleHalfZ-WallThick>; #declare Tower_Pos4 = <-CastleHalfX+WallThick, 0, CourtyardZ+CastleHalfZ-WallThick>; #declare Tower = union { cylinder { <0,0,0>, <0,TowerH,0>, TowerR } object { TowerCrenels(TowerR, TowerH-0.70, 0.75, 0.65, 14) } cone { <0,TowerH,0>, TowerR*0.98, <0,TowerH+1.25,0>, 0.12 } } // Full castle group union { object { Wall_Front } object { Wall_Back } object { Wall_Left } object { Wall_Right } object { Gatehouse texture { Tex_StoneAccent } } object { CrenelatedTop(CastleHalfX*2, WallTopY, CourtyardZ+CastleHalfZ-WallThick/2, WallThick, CrenW, CrenH, 0) } object { CrenelatedTop(CastleHalfX*2, WallTopY, CourtyardZ-CastleHalfZ+WallThick/2, WallThick, CrenW, CrenH, 1) } object { CrenelatedTop(CastleHalfZ*2, WallTopY, CourtyardZ, WallThick, CrenW, CrenH, 0) rotate <0,90,0> translate <-CastleHalfX+WallThick/2,0,0> } object { CrenelatedTop(CastleHalfZ*2, WallTopY, CourtyardZ, WallThick, CrenW, CrenH, 1) rotate <0,90,0> translate < CastleHalfX-WallThick/2,0,0> } object { Tower translate Tower_Pos1 } object { Tower translate Tower_Pos2 } object { Tower translate Tower_Pos3 } object { Tower translate Tower_Pos4 } texture { Tex_StoneBlocks } } // Gate door (wooden slab) precisely behind opening box { <-GateW/2, 0, CourtyardZ-CastleHalfZ+0.22>, < GateW/2, GateH, CourtyardZ-CastleHalfZ+0.38> texture { Tex_Wood } } // Inner dark passage behind the door to avoid "see-through" box { <-GateW/2, 0, CourtyardZ-CastleHalfZ+0.38>, < GateW/2, GateH, CourtyardZ-CastleHalfZ+1.35> texture { Tex_DarkPassage } } // Courtyard stage/platform for puppets #declare PlinthW = 7.2; #declare PlinthD = 4.4; #declare PlinthH = 0.26; box { <-PlinthW/2, 0, 1.25>, texture { Tex_StonePlinth } } // ---------- Marionette rig ---------- #declare RigY = 6.8; #declare BarLen = 10.6; #declare BarRad = 0.10; #declare BarZ = 3.05; // Crossbar cylinder { <-BarLen/2, RigY, BarZ>, , BarRad texture { Tex_Wood } } // Posts cylinder { <-BarLen/2, 0, BarZ>, <-BarLen/2, RigY, BarZ>, 0.15 texture { Tex_Wood } } cylinder { < BarLen/2, 0, BarZ>, < BarLen/2, RigY, BarZ>, 0.15 texture { Tex_Wood } } // Diagonal braces (simple) cylinder { <-BarLen/2, 2.2, BarZ>, <-BarLen/2+1.1, 0.25, BarZ>, 0.10 texture { Tex_Wood } } cylinder { < BarLen/2, 2.2, BarZ>, < BarLen/2-1.1, 0.25, BarZ>, 0.10 texture { Tex_Wood } } // ---------- Puppet macro (animated) ---------- #macro Puppet(P, OutfitTex) #local Bob = 0.18*Sway; #local ArmSwing = 35*sin(T*TAU + P*0.9); #local LegSwing = 28*sin(T*TAU + 1.2 + P*0.7); #local HeadTurn = 12*sin(T*TAU*0.5 + P*0.3); #local BodyH = 1.15; #local BodyR = 0.28; #local HeadR = 0.26; #local HipY = 0.20 + Bob; #local ShoulderY = HipY + BodyH*0.80; #local NeckY = HipY + BodyH; #local HeadY = NeckY + HeadR; #local ArmUpper = 0.52; #local ArmLower = 0.48; #local LegUpper = 0.62; #local LegLower = 0.58; #local JointR = 0.06; #local C = ; union { // torso cylinder { C+<0,HipY,0>, C+<0,HipY+BodyH,0>, BodyR texture { OutfitTex } } // head sphere { C+<0,HeadY,0>, HeadR texture { Tex_Skin } rotate <0, HeadTurn, 0> } // neck + shoulder + hip joints sphere { C+<0,NeckY,0>, JointR texture { Tex_Metal } } sphere { C+<-BodyR*0.95,ShoulderY,0>, JointR texture { Tex_Metal } } sphere { C+< BodyR*0.95,ShoulderY,0>, JointR texture { Tex_Metal } } sphere { C+<-BodyR*0.55,HipY,0>, JointR texture { Tex_Metal } } sphere { C+< BodyR*0.55,HipY,0>, JointR texture { Tex_Metal } } // left arm union { #local S = C+<-BodyR*0.95,ShoulderY,0>; #local E = S + <0,-ArmUpper,0>; #local W = E + <0,-ArmLower,0>; cylinder { S, E, 0.08 texture { Tex_Wood } } sphere { E, JointR texture { Tex_Metal } } cylinder { E, W, 0.07 texture { Tex_Wood } } sphere { W, 0.08 texture { Tex_Skin } } rotate } // right arm union { #local S = C+< BodyR*0.95,ShoulderY,0>; #local E = S + <0,-ArmUpper,0>; #local W = E + <0,-ArmLower,0>; cylinder { S, E, 0.08 texture { Tex_Wood } } sphere { E, JointR texture { Tex_Metal } } cylinder { E, W, 0.07 texture { Tex_Wood } } sphere { W, 0.08 texture { Tex_Skin } } rotate <-ArmSwing,0,0> } // left leg (green cloth "hose") union { #local H = C+<-BodyR*0.55,HipY,0>; #local K = H + <0,-LegUpper,0>; #local A = K + <0,-LegLower,0>; cylinder { H, K, 0.09 texture { Tex_ClothGreen } } sphere { K, JointR texture { Tex_Metal } } cylinder { K, A, 0.085 texture { Tex_ClothGreen } } box { A+<-0.12,-0.05,-0.16>, A+<0.12,0.05,0.08> texture { Tex_Wood } } rotate <-LegSwing,0,0> } // right leg union { #local H = C+< BodyR*0.55,HipY,0>; #local K = H + <0,-LegUpper,0>; #local A = K + <0,-LegLower,0>; cylinder { H, K, 0.09 texture { Tex_ClothGreen } } sphere { K, JointR texture { Tex_Metal } } cylinder { K, A, 0.085 texture { Tex_ClothGreen } } box { A+<-0.12,-0.05,-0.16>, A+<0.12,0.05,0.08> texture { Tex_Wood } } rotate } // whole puppet gentle turn/sway rotate <0, 7*sin(T*TAU + P*0.5), 0> } #end #declare P1x = -1.7; #declare P2x = 1.9; object { Puppet(P1x, Tex_ClothBlue) } object { Puppet(P2x, Tex_ClothRed ) } // ---------- Strings ---------- #declare StringRad = 0.02; #macro StringsForPuppet(P) #local Bob = 0.18*Sway; #local BodyH = 1.15; #local BodyR = 0.28; #local HeadR = 0.26; #local HipY = 0.20 + Bob; #local ShoulderY = HipY + BodyH*0.80; #local NeckY = HipY + BodyH; #local HeadY = NeckY + HeadR; #local C = ; #local TopMain = ; // head string cylinder { TopMain, C+<0,HeadY,0>, StringRad texture { Tex_Rope } } // hand strings (approx to wrist area) cylinder { TopMain+<-0.30,0,0>, C+<-BodyR*1.45,ShoulderY-0.95,0>, StringRad texture { Tex_Rope } } cylinder { TopMain+< 0.30,0,0>, C+< BodyR*1.45,ShoulderY-0.95,0>, StringRad texture { Tex_Rope } } #end StringsForPuppet(P1x) StringsForPuppet(P2x) // ---------- Simple props ---------- box { <-0.40, 3.05, CourtyardZ-CastleHalfZ+WallThick+0.02>, < 0.40, 4.70, CourtyardZ-CastleHalfZ+WallThick+0.05> texture { pigment { bozo color_map{ [0.00 color rgb <0.50,0.08,0.08>] [0.55 color rgb <0.82,0.18,0.16>] [1.00 color rgb <0.62,0.12,0.12>] } scale 0.30 turbulence 0.20 } normal { bumps 0.28 scale 0.09 } finish { diffuse 0.92 specular 0.07 roughness 0.12 } } } // Small training post / ring prop cylinder { <3.45, 0, 3.85>, <3.45, 0.90, 3.85>, 0.40 texture { Tex_Wood } } torus { 0.42, 0.05 rotate <90,0,0> translate <3.45, 0.22, 3.85> texture { Tex_Metal } } torus { 0.42, 0.05 rotate <90,0,0> translate <3.45, 0.70, 3.85> texture { Tex_Metal } }