#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 } #declare Finish_Matte = finish { diffuse 0.88 specular 0.08 roughness 0.08 }; #declare Finish_Stone = finish { diffuse 0.90 specular 0.05 roughness 0.14 }; #declare Finish_Wood = finish { diffuse 0.85 specular 0.06 roughness 0.10 }; #declare Col_Stone = color rgb <0.72, 0.74, 0.77>; #declare Col_Stone2 = color rgb <0.62, 0.64, 0.67>; #declare Col_Wood = color rgb <0.48, 0.32, 0.20>; #declare Col_Rope = color rgb <0.78, 0.70, 0.52>; #declare Col_Metal = color rgb <0.35, 0.36, 0.38>; #declare Col_Ground = color rgb <0.80, 0.82, 0.84>; #declare Col_Red = color rgb <0.86, 0.22, 0.20>; #declare Col_Blue = color rgb <0.22, 0.42, 0.85>; #declare Col_Green = color rgb <0.20, 0.65, 0.38>; #declare Col_Skin = color rgb <0.88, 0.74, 0.60>; #declare Col_Dark = color rgb <0.25, 0.26, 0.28>; 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 } // Courtyard ground plane { y, 0 pigment { Col_Ground } finish { diffuse 0.92 specular 0.04 roughness 0.14 } } // ---------- 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 // ---------- 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 } 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 } pigment { Col_Stone } finish { Finish_Stone } } // Gate door (wooden slab) precisely behind opening box { <-GateW/2, 0, CourtyardZ-CastleHalfZ+0.22>, < GateW/2, GateH, CourtyardZ-CastleHalfZ+0.38> pigment { Col_Wood } finish { Finish_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> pigment { Col_Dark } finish { Finish_Matte } } // Courtyard stage/platform for puppets #declare PlinthW = 7.2; #declare PlinthD = 4.4; #declare PlinthH = 0.26; box { <-PlinthW/2, 0, 1.25>, pigment { Col_Stone2 } finish { Finish_Stone } } // ---------- 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 pigment { Col_Wood } finish { Finish_Wood } } // Posts cylinder { <-BarLen/2, 0, BarZ>, <-BarLen/2, RigY, BarZ>, 0.15 pigment { Col_Wood } finish { Finish_Wood } } cylinder { < BarLen/2, 0, BarZ>, < BarLen/2, RigY, BarZ>, 0.15 pigment { Col_Wood } finish { Finish_Wood } } // Diagonal braces (simple) cylinder { <-BarLen/2, 2.2, BarZ>, <-BarLen/2+1.1, 0.25, BarZ>, 0.10 pigment { Col_Wood } finish { Finish_Wood } } cylinder { < BarLen/2, 2.2, BarZ>, < BarLen/2-1.1, 0.25, BarZ>, 0.10 pigment { Col_Wood } finish { Finish_Wood } } // ---------- Puppet macro (animated) ---------- #macro Puppet(P, OutfitCol) #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 pigment { OutfitCol } finish { Finish_Matte } } // head sphere { C+<0,HeadY,0>, HeadR pigment { Col_Skin } finish { Finish_Matte } rotate <0, HeadTurn, 0> } // neck + shoulder + hip joints sphere { C+<0,NeckY,0>, JointR pigment { Col_Metal } finish { Finish_Matte } } sphere { C+<-BodyR*0.95,ShoulderY,0>, JointR pigment { Col_Metal } finish { Finish_Matte } } sphere { C+< BodyR*0.95,ShoulderY,0>, JointR pigment { Col_Metal } finish { Finish_Matte } } sphere { C+<-BodyR*0.55,HipY,0>, JointR pigment { Col_Metal } finish { Finish_Matte } } sphere { C+< BodyR*0.55,HipY,0>, JointR pigment { Col_Metal } finish { Finish_Matte } } // 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 pigment { Col_Wood } finish { Finish_Wood } } sphere { E, JointR pigment { Col_Metal } finish { Finish_Matte } } cylinder { E, W, 0.07 pigment { Col_Wood } finish { Finish_Wood } } sphere { W, 0.08 pigment { Col_Skin } finish { Finish_Matte } } 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 pigment { Col_Wood } finish { Finish_Wood } } sphere { E, JointR pigment { Col_Metal } finish { Finish_Matte } } cylinder { E, W, 0.07 pigment { Col_Wood } finish { Finish_Wood } } sphere { W, 0.08 pigment { Col_Skin } finish { Finish_Matte } } rotate <-ArmSwing,0,0> } // left 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 pigment { Col_Green } finish { Finish_Matte } } sphere { K, JointR pigment { Col_Metal } finish { Finish_Matte } } cylinder { K, A, 0.085 pigment { Col_Green } finish { Finish_Matte } } box { A+<-0.12,-0.05,-0.16>, A+<0.12,0.05,0.08> pigment { Col_Wood } finish { Finish_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 pigment { Col_Green } finish { Finish_Matte } } sphere { K, JointR pigment { Col_Metal } finish { Finish_Matte } } cylinder { K, A, 0.085 pigment { Col_Green } finish { Finish_Matte } } box { A+<-0.12,-0.05,-0.16>, A+<0.12,0.05,0.08> pigment { Col_Wood } finish { Finish_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, Col_Blue) } object { Puppet(P2x, Col_Red ) } // ---------- 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 pigment { Col_Rope } finish { Finish_Matte } } // hand strings (approx to wrist area) cylinder { TopMain+<-0.30,0,0>, C+<-BodyR*1.45,ShoulderY-0.95,0>, StringRad pigment { Col_Rope } finish { Finish_Matte } } cylinder { TopMain+< 0.30,0,0>, C+< BodyR*1.45,ShoulderY-0.95,0>, StringRad pigment { Col_Rope } finish { Finish_Matte } } #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> pigment { color rgb <0.82, 0.18, 0.16> } finish { Finish_Matte } } cylinder { <3.45, 0, 3.85>, <3.45, 0.90, 3.85>, 0.40 pigment { Col_Wood } finish { Finish_Wood } } torus { 0.42, 0.05 rotate <90,0,0> translate <3.45, 0.22, 3.85> pigment { Col_Metal } finish { Finish_Matte } } torus { 0.42, 0.05 rotate <90,0,0> translate <3.45, 0.70, 3.85> pigment { Col_Metal } finish { Finish_Matte } }