/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * */ /* * INSTRUCTIONS * */ /* * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* //The Master of Puppets Font is easy to use. You may set various options or use the default values. The //following example demonstrates all you need to do to use the font: #declare MOP_Gap = .14; //Set the distance between characters (optional, default = .14) #declare MOP_Space = .65; //Set the distance between words (optional, default = .65) #declare MOP_FontRadius = .0625; //Set the radius of the strokes (optional, default = .0625) #declare MOP_ApplyKerning = yes; //Apply automatic kerning (yes or no) (optional, default = yes) #include "MasterOfPuppetsFont.inc" CreateMOP_TextObject ("Your text goes here.", MOP_Gap, MOP_Space, MOP_FontRadius, MOP_ApplyKerning) object {MOP_TextObject texture {YourTextureHere} translate <-MOP_TextObjectWidth / 2, 0, 0>} //The macro will create a CSG object called "MOP_TextObject" from the string you specify. It will set a //variable called MOP_TextObjectWidth and the object will extend from x = 0 to x = MOP_TextObjectWidth. //In the example above the object will be centered horizontally with the base of the characters at y = 0. //The characters will be scaled equally in all three dimensions to be 1 unit tall (not including //ascenders and descenders). The back of the object will be at z = 0 and the front of the object will //extend into the -z direction. //One special character is available, which is a smiley face and is designated by the "~" symbol. //In general, good values for MOP_FontRadius are > 0 to <= .063. At larger values the "e" will develop //glitches. At values larger than .0986 the "Q" will develop glitches. Different characters will have //problems at different radii but most characters will work fine even beyond .1. A value of .0625 best //matches the font on the Master of Puppets album cover. //Note that the rounded nature of this font is especially suited to metallic and/or shiny, reflective //textures. // * * * * * //Advanced instructions: //In the event that you need to apply different textures to the individual characters in your string, or //perform some other operation on the individual characters, you can use the following method instead of //the CreateMOP_TextObject () macro: #declare MOP_TextObject = object { #local CurrentX = 0; union { object {MOP_Character [MOP_CharacterIndex_P_] texture {P_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_P_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_O_] texture {O_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_O_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_V_] texture {V_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_V_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_DASH_] texture {DASH_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_DASH_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_R_] texture {R_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_R_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_a_] texture {a_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_a_] + MOP_FontRadius * 2 + MOP_Gap; object {MOP_Character [MOP_CharacterIndex_y_] texture {y_Color} translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [MOP_CharacterIndex_y_] + MOP_FontRadius * 2 + MOP_Gap; } //union translate //The lower left corner/back of the text object will be at the origin. #local S = 1 / (1 + MOP_FontRadius * 2); scale #declare MOP_TextObjectWidth = (CurrentX - MOP_Gap) * S; } //object object {MOP_TextObject translate <-MOP_TextObjectWidth / 2, 0, 0>} */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * */ /* * MACROS * */ /* * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #macro MeasureCharacter (CharacterIndex_, Shape_, Range_Lower_, Range_Upper_, NSteps_) #local I = CharacterIndex_; #local Shape = Shape_; #local Range_Lower = Range_Lower_; #local Range_Upper = Range_Upper_; #local NSteps = NSteps_; #local Step = (Range_Upper - Range_Lower) / (NSteps - 1); #local RayDirection_LeftToRight = x; #local RayDirection_RightToLeft = -x; #local StepCount = 0; #for (CurrentY, Range_Lower, Range_Upper, Step) #local RayStartPoint_LeftSide = <-10, CurrentY, -MOP_FontRadius>; #local RayStartPoint_RightSide = <10, CurrentY, -MOP_FontRadius>; #local IntersectionPoint_LeftSide = trace (Shape, RayStartPoint_LeftSide, RayDirection_LeftToRight); #if (IntersectionPoint_LeftSide.z != 0) //There's something here... #local IntersectionPoint_RightSide = trace (Shape, RayStartPoint_RightSide, RayDirection_RightToLeft); #declare SideDistance_Left [I] [StepCount] = IntersectionPoint_LeftSide.x; #declare SideDistance_Right [I] [StepCount] = MOP_CharacterWidth [I] - IntersectionPoint_RightSide.x + MOP_FontRadius * 2; //"+ MOP_FontRadius * 2" is unique to this project #else #declare SideDistance_Left [I] [StepCount] = -1; //Set to -1 if no intersection #declare SideDistance_Right [I] [StepCount] = -1; //Set to -1 if no intersection #declare CharacterFullVertical [I] = no; #end //#if #local StepCount = StepCount + 1; #end //#for #end //#macro MeasureCharacter #macro MeasureCharacterToCharacter (CharacterIndex0_, CharacterIndex1_, Range_Lower_, Range_Upper_, NSteps_) #local I = CharacterIndex0_; #local J = CharacterIndex1_; #local Range_Lower = Range_Lower_; #local Range_Upper = Range_Upper_; #local NSteps = NSteps_; #local Step = (Range_Upper - Range_Lower) / (NSteps - 1); #local MinimumDistance = 10; #local StepCount = 0; #for (CurrentY, Range_Lower, Range_Upper, Step) #if (SideDistance_Right [I] [StepCount] != -1 & SideDistance_Left [J] [StepCount] != -1) #local CurrentDistance = SideDistance_Right [I] [StepCount] + SideDistance_Left [J] [StepCount]; #if (CurrentDistance < MinimumDistance) #local MinimumDistance = CurrentDistance; #end //#if #end //#if #local StepCount = StepCount + 1; #end //#for #if (MinimumDistance = 10) //Characters never touch -1; #else abs (MinimumDistance); #end //#if #end //#macro MeasureCharacterToCharacter #macro XPoint (Point0_, Angle0_, Point1_, Angle1_) #local P0 = Point0_; #local A0 = Angle0_; #local P1 = Point1_; #local A1 = Angle1_; #local A0 = mod (A0, 360); #local A1 = mod (A1, 360); #if (P0.x = P1.x & P0.y = P1.y) #if (A0 = A1) #error "No unique intersection point exists." #else P0; #break #end //#if #end //#if #if (A1 - A0 = 0 | A1 - A0 = 180) #error "No unique intersection point exists." #end #if (P1.x < P0.x) #local TPoint = P1; #local TAngle = A1; #local P1 = P0; #local A1 = A0; #local P0 = TPoint; #local A0 = TAngle; #end //#if #local XOffset = P0.x; #local YOffset = P0.y; #local P0 = <0, 0, 0>; #local P1 = P1 - ; #if (P1.x = 0) #if (P1.y > 0) #local Theta = 90; #else #local Theta = 270; #end //#if #else #local Theta = degrees (atan (P1.y / P1.x)); #end //#if #local R2 = sqrt (P1.x * P1.x + P1.y * P1.y); #local A0 = A0 - Theta; #local A1 = A1 - Theta; #local P1 = ; #local A1 = 180 - A1; #local A3 = 180 - A0 - A1; #local R1 = R2 * sin (radians (A1)) / sin (radians (A3)); #local A0 = A0 + Theta; ; #end //#macro XPoint #macro RightAngleCornerFiller (Quadrant_, P0_) #local Quadrant = Quadrant_; #local P0 = P0_; object { union { intersection { torus {CornerRadius, R sturm rotate 90 * x translate } plane {y, CornerRadius} plane {x, CornerRadius} } //intersection difference { box {<0, 0, -R> } cylinder { , CornerRadius} } //difference } //union rotate (Quadrant * 90) * z translate P0 } //object #end //#macro RightAngleCornerFiller #macro ArbitraryAngleCornerFiller (P0_, A0_, A1_, R_, CornerRadius_) //P0: The point where the two cylinders that are to be connected meet //A0: The angle of one of the cylinders (+x = 0, +y = 90, -x = 180, -y = 270) //A1: The angle of the other cylinder //R: The radius of the cylinders that are to be connected //CornerRadius: The radius of the rounded corner #local P0 = P0_; #local A0 = A0_; #local A1 = A1_; #local R = R_; #local CornerRadius = CornerRadius_; #local A0 = mod (A0, 360); #if (A0 < 0) #local A0 = A0 + 360; #end #local A1 = mod (A1, 360); #if (A1 < 0) #local A1 = A1 + 360; #end #if (A0 > A1) #local Temp = A0; #local A0 = A1; #local A1 = Temp; #end //#if #local MiddleAngle = (A0 + A1) / 2; #local AngleDifference = A1 - A0; #if (AngleDifference > 180) #local AngleDifference = 360 - AngleDifference; #local MiddleAngle = MiddleAngle - 180; #local Flip = yes; #else #local Flip = no; #end //#if #local L0 = CornerRadius / sin (radians (AngleDifference / 2)); #local P1 = ; object { union { intersection { torus {CornerRadius, R sturm rotate 90 * x} plane {y, 0 inverse rotate (A0 + 90) * z} plane {y, 0 inverse rotate (A1 + 90) * z} } //intersection intersection { difference { box {<-L0 - .1, -L0 - .1, -R> } cylinder {<0, 0, -R - .1> <0, 0, R + .1>, CornerRadius} } //difference plane {y, 0 inverse rotate (A0 + 90) * z} plane {y, 0 inverse rotate (A1 + 90) * z} #if (Flip) plane {y, 0 rotate A0 * z translate P0 - P1} plane {y, 0 inverse rotate A1 * z translate P0 - P1} #else plane {y, 0 inverse rotate A0 * z translate P0 - P1} plane {y, 0 rotate A1 * z translate P0 - P1} #end //#if } //intersection } //union translate P1 } //object #end //#macro ArbitraryAngleCornerFiller #macro ComputeCornerLength (A0_, A1_, R_, CornerRadius_) #local A0 = A0_; #local A1 = A1_; #local R = R_; #local CornerRadius = CornerRadius_; #local A0 = mod (A0, 360); #if (A0 < 0) #local A0 = A0 + 360; #end #local A1 = mod (A1, 360); #if (A1 < 0) #local A1 = A1 + 360; #end #if (A0 > A1) #local Temp = A0; #local A0 = A1; #local A1 = Temp; #end //#if #local MiddleAngle = (A0 + A1) / 2; #local AngleDifference = A1 - A0; #if (AngleDifference > 180) #local MiddleAngle = MiddleAngle - 180; #end //#if #local L0 = CornerRadius / sin (radians (AngleDifference / 2)); abs (L0 * cos (radians (MiddleAngle))); #end //#macro ComputeCornerLength #macro ArbitraryVerticalBar (X0_, Y0_, Y1_, R_) #local X0 = X0_; #local Y0 = Y0_; #local Y1 = Y1_; #local R = R_; union { sphere {, R} sphere {, R} cylinder { , R} } //union #end //#macro ArbitraryVerticalBar #macro ArbitraryHorizontalBar (X0_, X1_, Y0_, R_) #local X0 = X0_; #local X1 = X1_; #local Y0 = Y0_; #local R = R_; union { sphere {, R} sphere {, R} cylinder { , R} } //union #end //#macro ArbitraryHorizontalBar #macro GenericClosedCircle_SS (Width_, Height_, C1_, C2_, R_) #local Width = Width_; #local Height = Height_; #local C1 = C1_; #local C2 = C2_; #local R = R_; sphere_sweep { b_spline 19 , R , R <0, C1, 0>, R <0, C1 + C2, 0>, R <0, Height - C1 - C2, 0>, R <0, Height - C1, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R <0, C1, 0>, R } //sphere_sweep #end //#macro GenericClosedCircle_SS #macro GenericCorner_Torus (CornerRadius_, R_, Spin_) #local CornerRadius = CornerRadius_; #local R = R_; #local Spin = Spin_; #local Corner = object { intersection { torus {CornerRadius, R sturm rotate 90 * x} plane {x, 0} plane {y, 0} } //intersection translate } //object object { union { sphere {, R} sphere {<0, CornerRadius, 0>, R} object {Corner} } //union rotate Spin * z } //object #end //#macro GenericCorner_Torus #macro ArbitraryRoundCorner (CornerRadius_, R_, A0_, Spin_, MirrorHorizontally_) #local CornerRadius = CornerRadius_; #local R = R_; #local A0 = A0_; #local Spin = Spin_; #local MirrorHorizontally = MirrorHorizontally_; object { intersection { torus {CornerRadius, R sturm rotate 90 * x} plane {x, 0} plane {y, 0 rotate A0 * z} } //intersection rotate Spin * z #if (MirrorHorizontally) rotate 180 * y #end //#if } //object #end //#macro ArbitraryRoundCorner #macro Hump (Width_, Height_, C1_, C2_, R_) #local Width = Width_; #local Height = Height_; #local C1 = C1_; #local C2 = C2_; #local R = R_; union { intersection { sphere_sweep { b_spline 12 <0, -2, 0>, R <0, 0, 0>, R <0, Height - C1 - C2, 0>, R <0, Height - C1, 0>, R , R , R , R , R , R , R , R , R } //sphere_sweep plane {y, 0 inverse} } //intersection sphere {, R} } //union #end //#macro Hump #macro CreateMOP_Characters (MOP_FontRadius) #local R = MOP_FontRadius; #local CornerRadius = R * 1.25; #local Height_Lower = .68; #local StandardInvisibleOffset = DefaultKerningDistance; #for (I, 0, NDefinedCharacters - 1) #declare MOP_IncludeInvisibleComponent [I] = no; #end //#for #local QUADRANT1 = 0; #local QUADRANT2 = 1; #local QUADRANT3 = 2; #local QUADRANT4 = 3; #local VerticalBar = object { union { cylinder {<0, 0, 0> <0, 1, 0>, R} sphere {<0, 0, 0>, R} sphere {<0, 1, 0>, R} } //union } //object #local ijDot = object { union { sphere {<0, 0, 0>, R} sphere {<0, .03, 0>, R} cylinder {<0, 0, 0> <0, .03, 0>, R} } //union translate (1 - .03) * y } //object #declare MOP_Character [MOP_CharacterIndex_A_] = object { #local A2 = .24; //Vertical #local A_A0 = 59; union { #local A1 = 2 * ComputeCornerLength (180 + A_A0, 0, R, CornerRadius); //Width of flat part #local A_L0 = 1 / sin (radians (A_A0)); #local A_L1 = A2 / sin (radians (A_A0)); #local A_P0 = ; #local A_P1 = A_P0 + ; #local A_P2 = ; #local A_P3 = ; #local A_P4 = ; sphere {<0, 0, 0>, R} sphere {A_P0, R} sphere {A_P1, R} sphere {A_P2, R} cylinder {<0, 0, 0> A_P0, R} cylinder {A_P0 A_P1, R} cylinder {A_P1 A_P2, R} cylinder {A_P3 A_P4, R} #local TCornerRadius = CornerRadius * 2; ArbitraryAngleCornerFiller (A_P0, 180 + A_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (A_P1, 180, -A_A0, R, CornerRadius) ArbitraryAngleCornerFiller (A_P3, 0, A_A0, R, CornerRadius) ArbitraryAngleCornerFiller (A_P3, 0, 180 + A_A0, R, TCornerRadius) ArbitraryAngleCornerFiller (A_P4, 180, -A_A0, R, TCornerRadius) ArbitraryAngleCornerFiller (A_P4, 180, 180 - A_A0, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_A_] = A_P2.x; } //object #declare MOP_Character [MOP_CharacterIndex_B_] = object { #local B1 = .12; #local B2 = 1.13; //Top width #local B3 = .2; #local B4 = .52; //Vertical #local B5 = B2 + .045; //Bottom width union { object {VerticalBar} intersection { sphere_sweep { //Top b_spline 12 <-3, 1, 0>, R <0, 1, 0>, R , R , R , R , R , R , R , R , R <0, B4, 0>, R <-3, B4, 0>, R } //sphere_sweep plane {x, 0 inverse} } //intersection intersection { sphere_sweep { //Bottom b_spline 12 <-3, B4, 0>, R <0, B4, 0>, R , R , R , R , R , R , R , R , R <0, 0, 0>, R <-3, 0, 0>, R } //sphere_sweep plane {x, 0 inverse} } //intersection RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, B4, 0>) RightAngleCornerFiller (QUADRANT4, <0, B4, 0>) RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_B_] = B5; } //object #declare MOP_Character [MOP_CharacterIndex_C_] = object { #local C1 = .12; #local C1B = .09; #local C1C = .12; #local C2 = 1.21; //Width #local C3 = .2; #local C3B = .14; #local C3C = .2; #local C4 = .02; //Shorten top width #local C5 = .02; sphere_sweep { b_spline 18 , R , R , R , R , R , R , R <0, C1, 0>, R <0, C1 + C3, 0>, R <0, 1 - C1 - C3, 0>, R <0, 1 - C1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_C_] = C2 + C5; #declare MOP_InvisibleComponent [MOP_CharacterIndex_C_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_C_] = yes; #local C6 = StandardInvisibleOffset; #local C7 = MOP_CharacterWidth [MOP_CharacterIndex_C_] - C4 - C6 - .004; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_D_] = object { #local D1 = .12; #local D2 = 1.25; //Width #local D3 = .2; union { object {VerticalBar} intersection { sphere_sweep { b_spline 12 <-3, 1, 0>, R <0, 1, 0>, R , R , R , R , R , R , R , R , R <0, 0, 0>, R <-3, 0, 0>, R } //sphere_sweep plane {x, 0 inverse} } //intersection RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_D_] = D2; } //object #declare MOP_Character [MOP_CharacterIndex_E_] = object { #local E1 = .98; //Top and bottom bars #local E2 = .945; //Middle bar #local E3 = .52; //Vertical union { object {VerticalBar} sphere {, R} cylinder {<0, 0, 0> , R} sphere {, R} cylinder {<0, E3, 0> , R} sphere {, R} cylinder {<0, 1, 0> , R} RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, E3, 0>) RightAngleCornerFiller (QUADRANT4, <0, E3, 0>) RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_E_] = E1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_E_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_E_] = yes; #local E4 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_F_] = object { #local F1 = .95; //Top bar #local F2 = .91; //Bottom bar #local F3 = .52; //Vertical union { object {VerticalBar} sphere {, R} cylinder {<0, F3, 0> , R} sphere {, R} cylinder {<0, 1, 0> , R} RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, F3, 0>) RightAngleCornerFiller (QUADRANT4, <0, F3, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_F_] = F1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_F_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_F_] = yes; #local F4 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_G_] = object { #local G1 = .12; #local G2 = 1.26; //Width #local G3 = .2; #local G4 = G1 + G3 + .115; //Vertical, G4 must be > G1 + G3 #local G5 = G2 / 2 + .04; union { difference { sphere_sweep { b_spline 18 , R , R , R , R , R , R , R , R <0, G1, 0>, R <0, G1 + G3, 0>, R <0, 1 - G1 - G3, 0>, R <0, 1 - G1, 0>, R , R , R , R , R , R , R } //sphere_sweep box { } } //difference ArbitraryHorizontalBar (G5, G2, G4, R) RightAngleCornerFiller (QUADRANT3, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_G_] = G2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_G_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_G_] = yes; #local G6 = StandardInvisibleOffset; #local G7 = G2 - .02 - G6; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_H_] = object { #local H1 = 1.1; //Width #local H2 = .52; //Vertical union { object {VerticalBar} object {VerticalBar translate H1 * x} cylinder {<0, H2, 0> , R} RightAngleCornerFiller (QUADRANT1, <0, H2, 0>) RightAngleCornerFiller (QUADRANT4, <0, H2, 0>) RightAngleCornerFiller (QUADRANT2, ) RightAngleCornerFiller (QUADRANT3, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_H_] = H1; } //object #declare MOP_Character [MOP_CharacterIndex_I_] = object { object {VerticalBar} #declare MOP_CharacterWidth [MOP_CharacterIndex_I_] = 0; } //object #declare MOP_Character [MOP_CharacterIndex_J_] = object { #local J1 = .12; #local J2 = 1.11; //Width #local J3 = .2; #local J4 = J1 + J3 + .01; //J4 must be > J1 + J3 union { intersection { sphere_sweep { b_spline 11 <0, J4, 0>, R <0, J1 + J3, 0>, R <0, J1, 0>, R , R , R , R , R , R , R , R , R } //sphere_sweep plane {y, 1} } //intersection sphere {, R} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_J_] = J2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_J_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_J_] = yes; #local J5 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_K_] = object { #local K1 = .29; //Width of horizontal bar #local K2 = .52; //Vertical #switch (R) //Adjust length of rounded corner #range (0, .0845) #local K4 = 6.5; #break #range (.0845, .1) #local K4 = 6.5 - (R - .0845) / (.1 - .0845) * 1.8; #break #range (.1, 999) #local K4 = 3; #break #end //#switch #local K_A0 = 30; union { object {VerticalBar} sphere {, R} cylinder {<0, K2, 0> , R} #local K3_Top = sin (radians (90 - K_A0)) * (1 - K2) / sin (radians (K_A0)); #local K3_Bottom = sin (radians (90 - K_A0)) * K2 / sin (radians (K_A0)); #local K_L0_Top = sqrt (K3_Top * K3_Top + (1 - K2) * (1 - K2)); #local K_L0_Bottom = sqrt (K3_Bottom * K3_Bottom + K2 * K2); #local Bar_Top = object { union { cylinder {<0, 0, 0> , R} sphere {, R} } //union } //object #local Bar_Bottom = object { union { cylinder {<0, 0, 0> , R} sphere {, R} } //union } //object object {Bar_Top rotate K_A0 * z translate } object {Bar_Bottom rotate -K_A0 * z translate } #local TCornerRadius = CornerRadius * K4; ArbitraryAngleCornerFiller (, 180, K_A0, R, TCornerRadius) ArbitraryAngleCornerFiller (, 180, -K_A0, R, TCornerRadius) ArbitraryAngleCornerFiller (, K_A0, -K_A0, R, CornerRadius) RightAngleCornerFiller (QUADRANT4, <0, K2, 0>) RightAngleCornerFiller (QUADRANT1, <0, K2, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_K_] = K1 + K3_Bottom; #declare MOP_InvisibleComponent [MOP_CharacterIndex_K_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_K_] = yes; #local K3 = StandardInvisibleOffset; cylinder {<0, 0, 0> <0, 1, 0>, R translate } } //object } //object #declare MOP_Character [MOP_CharacterIndex_L_] = object { #local L1 = 1.03; //Width union { object {VerticalBar} sphere {, R} cylinder {<0, 0, 0> , R} RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_L_] = L1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_L_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_L_] = yes; #local L2 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_M_] = object { #local M_A0 = 35; union { #local M1 = CornerRadius + ComputeCornerLength (180, 270 + M_A0, R, CornerRadius); //Width of flat part #local M_L0 = 1 / sin (radians (90 - M_A0)); #local M_P0 = ; #local M_P1 = ; //Center #local M_P2 = ; #local M_P3 = M_P2 + ; object {VerticalBar} //Left side sphere {M_P0, R} cylinder {<0, 1, 0> M_P0, R} cylinder {M_P0 M_P1, R} sphere {M_P1, R} //Center sphere {M_P2, R} cylinder {M_P1 M_P2, R} cylinder {M_P2 M_P3, R} object {VerticalBar translate M_P3.x * x} //Right side ArbitraryAngleCornerFiller (M_P0, 180, 270 + M_A0, R, CornerRadius) ArbitraryAngleCornerFiller (M_P2, 0, 270 - M_A0, R, CornerRadius) ArbitraryAngleCornerFiller (M_P1, 90 + M_A0, 90 - M_A0, R, CornerRadius) //Center RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT3, M_P3) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_M_] = M_P3.x; } //object #declare MOP_Character [MOP_CharacterIndex_N_] = object { #local N_A0 = 44.5; union { #local N1 = CornerRadius + ComputeCornerLength (180, 270 + N_A0, R, CornerRadius); //Width of flat part #local N_L0 = 1 / sin (radians (90 - N_A0)); #local N_P0 = <0, 1, 0>; #local N_P1 = N_P0 + ; #local N_P2 = ; #local N_P3 = N_P2 + ; object {VerticalBar} //Left side object {VerticalBar translate N_P3.x * x} //Right side sphere {N_P1, R} sphere {N_P2, R} cylinder {N_P0 N_P1, R} cylinder {N_P1 N_P2, R} cylinder {N_P2 N_P3, R} ArbitraryAngleCornerFiller (N_P1, 180, 270 + N_A0, R, CornerRadius) ArbitraryAngleCornerFiller (N_P2, 0, 90 + N_A0, R, CornerRadius) RightAngleCornerFiller (QUADRANT4, N_P0) RightAngleCornerFiller (QUADRANT2, N_P3) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_N_] = N_P3.x; } //object #declare MOP_Character [MOP_CharacterIndex_O_] = object { #local O1 = .15; #local O2 = 1.3; //Width #local O3 = .2; GenericClosedCircle_SS (O2, 1, O1, O3, R) #declare MOP_CharacterWidth [MOP_CharacterIndex_O_] = O2; } //object #declare MOP_Character [MOP_CharacterIndex_P_] = object { #local P1 = .12; #local P2 = 1.1; //Width #local P3 = .2; #local P4 = .445; //Vertical union { object {VerticalBar} intersection { sphere_sweep { b_spline 12 <-3, 1, 0>, R <0, 1, 0>, R , R , R , R , R , R , R , R , R <0, P4, 0>, R <-3, P4, 0>, R } //sphere_sweep plane {x, 0 inverse} } //intersection RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, P4, 0>) RightAngleCornerFiller (QUADRANT4, <0, P4, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_P_] = P2; } //object #declare MOP_Character [MOP_CharacterIndex_Q_] = object { #local Q1 = MOP_CharacterWidth [MOP_CharacterIndex_O_]; //Width #local Q2 = .26; //Outside length of tail #local Q3 = .385; //Inside length of tail #switch (R) //Adjust length of flattened portion #range (0, .06) #local Q4 = .085; #break #range (.06, .0986) #local Q4 = .085 - (R - .06) / (.0986 - .06) * .085; #break #range (.0986, 999) #local Q4 = 0; #break #end //#switch #local Q_A0 = 32; union { difference { object {MOP_Character [MOP_CharacterIndex_O_]} box { } } //difference #local QCornerRadius = .28; #local Q_P0 = ; #local QCorner_Left = ArbitraryRoundCorner (QCornerRadius, R, 45, 0, yes) #local QCorner_Right = ArbitraryRoundCorner (QCornerRadius, R, 45, 90, no) object {QCorner_Left translate } cylinder { , R} sphere {, R} sphere {, R} object {QCorner_Right translate } #if (Q4 > 0) cylinder { , R} sphere {, R} #end //#if sphere {, R} #local Q_P0_Left = Q_P0 + ; #local Q_P0_Right = Q_P0 + ; cylinder {Q_P0_Left, Q_P0_Right, R} #local QTail = object { union { cylinder {<-Q3, 0, 0> , R} sphere {<-Q3, 0, 0>, R} sphere {, R} } //union } //object #local Q_P1 = <(Q_P0_Left.x + Q_P0_Right.x) / 2, (Q_P0_Left.y + Q_P0_Right.y) / 2, 0>; object {QTail rotate -Q_A0 * z translate Q_P1} ArbitraryAngleCornerFiller (Q_P1, 45, 180 - Q_A0, R, CornerRadius) ArbitraryAngleCornerFiller (Q_P1, 45, -Q_A0, R, CornerRadius) ArbitraryAngleCornerFiller (Q_P1, -135, 180 - Q_A0, R, CornerRadius) ArbitraryAngleCornerFiller (Q_P1, -135, -Q_A0, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_Q_] = Q_P1.x + Q2 * cos (radians (Q_A0)); } //object #declare MOP_Character [MOP_CharacterIndex_R_] = object { #local R1 = .12; #local R2 = 1.12; //Top width #local R3 = .2; #local R4 = .445; //Vertical #local R5 = R2 - .015; //Bottom width union { object {VerticalBar} intersection { sphere_sweep { //Top b_spline 12 <-3, 1, 0>, R <0, 1, 0>, R , R , R , R , R , R , R , R , R <0, R4, 0>, R <-3, R4, 0>, R } //sphere_sweep plane {x, 0 inverse} } //intersection union { intersection { sphere_sweep { //Bottom b_spline 8 <-3, R4, 0>, R <0, R4, 0>, R , R , R , R , R , R , R } //sphere_sweep plane {x, 0 inverse} plane {y, 0 inverse} } //intersection sphere {, R} } //union RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, <0, R4, 0>) RightAngleCornerFiller (QUADRANT4, <0, R4, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_R_] = R2; } //object #declare MOP_Character [MOP_CharacterIndex_S_] = object { #local S1 = .12; #local S1B = .11; #local S1C = .12; #local S2 = 1.11; //Top width #local S3 = .12; #local S3B = .155; #local S3C = .2; #local S4 = .5; //Vertical #local S5 = .01; #local S7 = .015; //Additional bottom width sphere_sweep { b_spline 26 <-S5, S1B + S3B + .001, 0>, R <-S5, S1B + S3B, 0>, R <-S5, S1, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R <0, S4 + S1, 0>, R <-S5, S4 + S1 + S3, 0>, R <-S5, 1 - S1 - S3, 0>, R <0, 1 - S1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep translate S5 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_S_] = S2 + S7 + S5 * 2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_S_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_S_] = yes; #local S8 = StandardInvisibleOffset; #local S9 = S2 + .01; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_T_] = object { #local T1 = 1.17; //Top bar union { sphere {, R} cylinder { , R} ArbitraryHorizontalBar (0, T1, 1, R) RightAngleCornerFiller (QUADRANT3, ) RightAngleCornerFiller (QUADRANT4, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_T_] = T1; } //object #declare MOP_Character [MOP_CharacterIndex_U_] = object { #local U1 = .12; #local U2 = 1.18; //Width #local U3 = .2; union { intersection { sphere_sweep { b_spline 12 , R , R , R , R , R , R , R , R <0, U1, 0>, R <0, U1 + U3, 0>, R <0, 1, 0>, R <0, 2, 0>, R } //sphere_sweep plane {y, 1} } //intersection sphere {<0, 1, 0>, R} sphere {, R} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_U_] = U2; } //object #declare MOP_Character [MOP_CharacterIndex_V_] = object { #local V_A0 = 61; union { #local V1 = 2 * ComputeCornerLength (180 + V_A0, 0, R, CornerRadius); //Width of flat part #local V_L0 = 1 / sin (radians (V_A0)); #local V2 = V_L0 * cos (radians (V_A0)); #local V_P0 = ; #local V_P1 = V_P0 + ; #local V_P2 = ; sphere {<0, 1, 0>, R} sphere {V_P0, R} sphere {V_P1, R} sphere {V_P2, R} cylinder {<0, 1, 0> V_P0, R} cylinder {V_P0 V_P1, R} cylinder {V_P1 V_P2, R} ArbitraryAngleCornerFiller (V_P0, 180 - V_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (V_P1, 180, V_A0, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_V_] = V_P2.x; } //object #declare MOP_Character [MOP_CharacterIndex_W_] = object { #local W_A0 = 21; union { #local W1 = 2 * ComputeCornerLength (90 + W_A0, 0, R, CornerRadius); //Width of flat part #local W_L0 = 1 / sin (radians (90 - W_A0)); #local W2 = W_L0 * cos (radians (90 - W_A0)); #local W_P0 = <0, 1, 0>; #local W_P1 = ; #local W_P2 = W_P1 + ; #local W_P3 = ; #local W_P4 = W_P3 + ; #local W_P5 = ; #local W_P6 = W_P5 + ; #local W_P7 = ; sphere {W_P0, R} sphere {W_P1, R} sphere {W_P2, R} sphere {W_P3, R} sphere {W_P4, R} sphere {W_P5, R} sphere {W_P6, R} sphere {W_P7, R} cylinder {W_P0 W_P1, R} cylinder {W_P1 W_P2, R} cylinder {W_P2 W_P3, R} cylinder {W_P3 W_P4, R} cylinder {W_P4 W_P5, R} cylinder {W_P5 W_P6, R} cylinder {W_P6 W_P7, R} ArbitraryAngleCornerFiller (W_P1, 90 + W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P2, 90 - W_A0, 180, R, CornerRadius) ArbitraryAngleCornerFiller (W_P3, 270 - W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P4, 270 + W_A0, 180, R, CornerRadius) ArbitraryAngleCornerFiller (W_P5, 90 + W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P6, 90 - W_A0, 180, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_W_] = W_P7.x; } //object #declare MOP_Character [MOP_CharacterIndex_X_] = object { #local X1 = .56; //Vertical #local X2 = .05; //Top vertical offset #local X3 = .1 / R + .05; //CornerRadius multiplier #local X_A0 = 44; #local X_L0_Bottom = X1 / sin (radians (X_A0)); #local X_L0_Top = (1 - (X1 - X2)) / sin (radians (X_A0)); #local X_P0 = ; #local X_P4 = X_P0 - <0, X2, 0>; #local X_P1 = ; #local X_P2 = ; #local X_P3 = ; #local X_P5 = XPoint (<0, 0, 0>, X_A0, X_P2, -X_A0) #local X_P6 = XPoint (X_P1, 180 - X_A0, X_P3, X_A0) union { sphere {<0, 0, 0>, R} //Bottom left intersection { cylinder {<0, 0, 0> X_P0, R} plane {y, 0 rotate -X_A0 * z translate X_P4} } //intersection sphere {X_P1, R} //Bottom right intersection { cylinder {X_P1 X_P0, R} plane {y, 0 rotate X_A0 * z translate X_P4} } //intersection sphere {X_P2, R} //Top left intersection { cylinder {X_P2 X_P4, R} plane {y, 0 inverse rotate X_A0 * z translate X_P0} } //intersection sphere {X_P3, R} //Top right intersection { cylinder {X_P3 X_P4, R} plane {y, 0 inverse rotate -X_A0 * z translate X_P0} } //intersection #local TCornerRadius = CornerRadius * X3; ArbitraryAngleCornerFiller (X_P0, 180 + X_A0, -X_A0, R, TCornerRadius) //Bottom ArbitraryAngleCornerFiller (X_P4, 180 - X_A0, X_A0, R, TCornerRadius) //Top ArbitraryAngleCornerFiller (X_P5, 180 - X_A0, 180 + X_A0, R, TCornerRadius) //Left ArbitraryAngleCornerFiller (X_P6, X_A0, -X_A0, R, TCornerRadius) //Right } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_X_] = X_P1.x; #declare MOP_InvisibleComponent [MOP_CharacterIndex_X_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_X_] = yes; #local X4 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_Y_] = object { #local Y1 = .44; //Vertical #local Y3 = 1.2; //Width #local Y4 = Y3 / 2; #local Y_A0 = degrees (atan (Y4 / (1 - Y1))); union { sphere {<0, 0, 0>, R} sphere {<0, Y1, 0>, R} cylinder {<0, 0, 0> <0, Y1, 0>, R} #local Y_L0 = sqrt (Y4 * Y4 + (1 - Y1) * (1 - Y1)); #local Bar = object { union { cylinder {<0, 0, 0> , R} sphere {, R} } //union } //object object {Bar rotate (90 + Y_A0) * z translate <0, Y1, 0>} object {Bar rotate (90 - Y_A0) * z translate <0, Y1, 0>} #local TCornerRadius = CornerRadius * 2; ArbitraryAngleCornerFiller (<0, Y1, 0>, 90 + Y_A0, 270, R, TCornerRadius) ArbitraryAngleCornerFiller (<0, Y1, 0>, 90 - Y_A0, 270, R, TCornerRadius) ArbitraryAngleCornerFiller (<0, Y1, 0>, 90 + Y_A0, 90 - Y_A0, R, CornerRadius) } //union translate Y4 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_Y_] = Y3; } //object #declare MOP_Character [MOP_CharacterIndex_Z_] = object { #local Z1 = 1.15; //Width #local Z2 = .03; //Shorten top left #local Z3 = .02; //Shorten top right #local Z_A0 = degrees (atan (1 / (Z1 - Z3))); #local Z_P0 = ; #local Z_P1 = <0, 0, 0>; #local Z_P2 = ; #local Z_P3 = ; union { ArbitraryHorizontalBar (0, Z1, 0, R) //Bottom bar ArbitraryHorizontalBar (Z2, Z1 - Z3, 1, R) //Top bar cylinder {Z_P1 Z_P2, R} ArbitraryAngleCornerFiller (Z_P1, Z_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (Z_P2, 180 + Z_A0, 180, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_Z_] = Z1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_Z_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_Z_] = yes; #local Z4 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_a_] = object { #local V0 = Height_Lower; #local V1 = .87; //Width #local V2 = .36; //Height of circle #local V3 = .03; //Top offset #local C1 = .1; #local C2 = .2; #local C3 = .08; #local C4 = .00001; #local C5 = .16; union { sphere_sweep { b_spline 19 , R , R <0, C3, 0>, R <0, V2 / 2 - C4, 0>, R <0, V2 / 2 + C4, 0>, R <0, V2 - C3, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R <0, C3, 0>, R } //sphere_sweep intersection { sphere_sweep { b_spline 10 , R , R , R , R , R , R , R , R , R , R } //sphere_sweep plane {y, 0 inverse} } //intersection sphere {, R} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_a_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_a_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_a_] = yes; #local V4 = StandardInvisibleOffset; #local V5 = .046; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_b_] = object { #local V0 = Height_Lower; #local V1 = .89; //Width #local C1 = .12; #local C2 = .2; union { object {VerticalBar} GenericClosedCircle_SS (V1, V0, C1, C2, R) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_b_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_c_] = object { #local V0 = Height_Lower; #local V1 = .86; //Width #local V3 = 0; //Top offset #local C1 = .12; #local C2 = .2; sphere_sweep { b_spline 16 , R , R , R , R , R , R <0, C1, 0>, R <0, C1 + C2, 0>, R <0, V0 - C1 - C2, 0>, R <0, V0 - C1, 0>, R , R , R , R , R , R , R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_c_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_c_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_c_] = yes; #local V4 = StandardInvisibleOffset; #local V5 = V1 - .02; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_d_] = object { MOP_Character [MOP_CharacterIndex_b_] rotate 180 * y translate MOP_CharacterWidth [MOP_CharacterIndex_b_] * x #declare MOP_CharacterWidth [MOP_CharacterIndex_d_] = MOP_CharacterWidth [MOP_CharacterIndex_b_]; } //object #declare MOP_Character [MOP_CharacterIndex_e_] = object { #local V0 = Height_Lower; #local V1 = .89; //Width #local V2 = .24; //Corner radius #local V4 = .36; //Vertical #local A0 = 30; #local V3 = V2 - V2 * cos (radians (A0)); //Bottom offset #local eCorner = object { union { intersection { torus {V2, R sturm rotate 90 * x} plane {x, 0 inverse} plane {y, 0 rotate -A0 * z} } //intersection sphere {, R} } //union translate <-V2, V2, 0> } //object union { sphere {, R} sphere {, R} cylinder { , R} cylinder {<0, V2, 0> <0, V0 - V2, 0>, R} cylinder { , R} cylinder { , R} cylinder {<0, V4, 0> , R} object {eCorner translate } object {GenericCorner_Torus (V2, R, 0)} object {GenericCorner_Torus (V2, R, -90) translate <0, V0, 0>} object {GenericCorner_Torus (V2, R, -180) translate } RightAngleCornerFiller (QUADRANT2, ) RightAngleCornerFiller (QUADRANT1, <0, V4, 0>) RightAngleCornerFiller (QUADRANT4, <0, V4, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_e_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_e_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_e_] = yes; #local V5 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_f_] = object { #local V0 = Height_Lower; //Vertical #local V1 = .15; //Corner radius #local V2 = .18; //Left width #local V3 = .38; //Right width union { sphere {<0, 0, 0>, R} sphere {, R} cylinder {<0, 0, 0> <0, 1 - V1, 0>, R} cylinder { , R} object {GenericCorner_Torus (V1, R, -90) translate 1 * y} ArbitraryHorizontalBar (-V2, V3, V0, R) RightAngleCornerFiller (QUADRANT1, <0, V0, 0>) RightAngleCornerFiller (QUADRANT2, <0, V0, 0>) RightAngleCornerFiller (QUADRANT3, <0, V0, 0>) RightAngleCornerFiller (QUADRANT4, <0, V0, 0>) } //union translate V2 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_f_] = V2 + V3; #declare MOP_InvisibleComponent [MOP_CharacterIndex_f_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_f_] = yes; #local V4 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_g_] = object { #local V0 = Height_Lower; #local V1 = .89; //Width #local V3 = .04; //Vertical circle offset #local V5 = .01; //Horizontal offset #local V6 = -.28; //Descender distance #local C1 = .12; #local C2 = .2; union { intersection { sphere_sweep { b_spline 10 , R , R , R , R , R , R , R , R , R , R } //sphere_sweep plane {y, V0} } //intersection sphere {, R} object {GenericClosedCircle_SS (V1, V0 - V3, C1, C2, R) translate V3 * y} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_g_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_g_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_g_] = yes; #local V4 = StandardInvisibleOffset; #local V7 = .03; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_h_] = object { #local V0 = Height_Lower; #local V1 = .85; //Width #local C1 = .12; #local C2 = .2; union { object {VerticalBar} Hump (V1, V0, C1, C2, R) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_h_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_i_] = object { #local V0 = Height_Lower; union { ArbitraryVerticalBar (0, 0, V0, R) object {ijDot} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_i_] = 0; #declare MOP_InvisibleComponent [MOP_CharacterIndex_i_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_i_] = yes; cylinder {<0, V0, 0> <0, 1 - .03, 0>, R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_j_] = object { #local V0 = Height_Lower; #local V1 = -.28; //Descender distance (from "g") #local V2 = .13; //Corner radius union { ArbitraryVerticalBar (0, V1 + V2, V0, R) object {ijDot} object {GenericCorner_Torus (V2, R, -270) translate V1 * y} } //union translate V2 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_j_] = V2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_j_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_j_] = yes; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_k_] = object { #local V0 = Height_Lower; #local K1 = .21; //Width of horizontal bar #local K2 = .36; //Vertical #switch (R) //Adjust length of rounded corner #range (0, .055) #local K4 = 6.5; #break #range (.055, .0625) #local K4 = 5.45; #break #range (.0625, .08) #local K4 = 3.55; #break #range (.08, .1) #local K4 = 2.2; #break #range (.1, .12) #local K4 = 1.27; #break #range (.12, 999) #local K4 = -1; #break #end //#switch #local K_A0 = 33; union { object {VerticalBar} sphere {, R} cylinder {<0, K2, 0> , R} #local K3_Top = sin (radians (90 - K_A0)) * (V0 - K2) / sin (radians (K_A0)); #local K3_Bottom = sin (radians (90 - K_A0)) * K2 / sin (radians (K_A0)); #local K_L0_Top = sqrt (K3_Top * K3_Top + (V0 - K2) * (V0 - K2)); #local K_L0_Bottom = sqrt (K3_Bottom * K3_Bottom + K2 * K2); #local Bar_Top = object { union { cylinder {<0, 0, 0> , R} sphere {, R} } //union } //object #local Bar_Bottom = object { union { cylinder {<0, 0, 0> , R} sphere {, R} } //union } //object object {Bar_Top rotate K_A0 * z translate } object {Bar_Bottom rotate -K_A0 * z translate } #if (R <= .12) #local TCornerRadius = CornerRadius * K4; ArbitraryAngleCornerFiller (, 180, K_A0, R, TCornerRadius) ArbitraryAngleCornerFiller (, 180, -K_A0, R, TCornerRadius) #end //#if ArbitraryAngleCornerFiller (, K_A0, -K_A0, R, CornerRadius) RightAngleCornerFiller (QUADRANT4, <0, K2, 0>) RightAngleCornerFiller (QUADRANT1, <0, K2, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_k_] = K1 + K3_Bottom; #declare MOP_InvisibleComponent [MOP_CharacterIndex_k_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_k_] = yes; #local K5 = StandardInvisibleOffset; intersection { cylinder {<0, 0, 0> <0, 1, 0>, R translate } plane {y, 0 rotate K_A0 * z translate } plane {y, 0 inverse rotate -K_A0 * z translate } } //intersection } //object } //object #declare MOP_Character [MOP_CharacterIndex_l_] = object { object {VerticalBar} #declare MOP_CharacterWidth [MOP_CharacterIndex_l_] = 0; } //object #declare MOP_Character [MOP_CharacterIndex_m_] = object { #local V0 = Height_Lower; #local V1 = .77; //Width #local C1 = .12; #local C2 = .2; union { ArbitraryVerticalBar (0, 0, V0, R) Hump (V1, V0, C1, C2, R) object {Hump (V1, V0, C1, C2, R) translate V1 * x} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_m_] = V1 * 2; } //object #declare MOP_Character [MOP_CharacterIndex_n_] = object { #local V0 = Height_Lower; #local V1 = .85; //Width #local C1 = .12; #local C2 = .2; union { ArbitraryVerticalBar (0, 0, V0, R) Hump (V1, V0, C1, C2, R) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_n_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_o_] = object { #local V0 = Height_Lower; #local V1 = .94; //Width #local C1 = .12; #local C2 = .2; GenericClosedCircle_SS (V1, V0, C1, C2, R) #declare MOP_CharacterWidth [MOP_CharacterIndex_o_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_p_] = object { #local V0 = Height_Lower; #local V1 = .89; //Width #local V3 = -.28; //Descender distance (from "g") #local C1 = .12; #local C2 = .2; union { ArbitraryVerticalBar (0, V3, V0, R) GenericClosedCircle_SS (V1, V0, C1, C2, R) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_p_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_q_] = object { MOP_Character [MOP_CharacterIndex_p_] rotate 180 * y translate MOP_CharacterWidth [MOP_CharacterIndex_p_] * x #declare MOP_CharacterWidth [MOP_CharacterIndex_q_] = MOP_CharacterWidth [MOP_CharacterIndex_p_]; } //object #declare MOP_Character [MOP_CharacterIndex_r_] = object { #local V0 = Height_Lower; #local V1 = .7; //Width #local C1 = .12; #local C2 = .2; union { ArbitraryVerticalBar (0, 0, V0, R) intersection { sphere_sweep { b_spline 11 <0, -2, 0>, R <0, 0, 0>, R <0, V0 - C1 - C2, 0>, R <0, V0 - C1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep plane {y, 0 inverse} } //intersection } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_r_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_s_] = object { #local V0 = Height_Lower; #local V1 = .87; //Width #local V2 = .34; //Vertical #local V3 = .01; //Left top indent #local V4 = .02; //Right top indent #local V6 = V2 / 2; #local V7 = (V2 + V0) / 2; #local C1 = .08; #local C2 = .16; #local C3 = .00001; sphere_sweep { b_spline 25 <0, C1 + .11, 0>, R <0, C1 + .1, 0>, R <0, C1, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_s_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_s_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_s_] = yes; #local V8 = StandardInvisibleOffset; #local V9 = V1 - V4 - .014; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_t_] = object { #local V0 = Height_Lower; #local V1 = .18; //Left width #local V2 = .53; //Right width #local V4 = .56; //Bottom width #local V5 = .86; //Stem height #local V6 = .16; //Hook height extension #local C1 = .08; #local C2 = .16; union { intersection { sphere_sweep { b_spline 11 <0, V5 + 2, 0>, R <0, V5, 0>, R <0, C1 + C2, 0>, R <0, C1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep plane {y, V5} } //intersection sphere {<0, V5, 0>, R} ArbitraryHorizontalBar (-V1, V2, V0, R) RightAngleCornerFiller (QUADRANT1, <0, V0, 0>) RightAngleCornerFiller (QUADRANT2, <0, V0, 0>) RightAngleCornerFiller (QUADRANT3, <0, V0, 0>) RightAngleCornerFiller (QUADRANT4, <0, V0, 0>) } //union translate V1 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_t_] = V1 + V4; #declare MOP_InvisibleComponent [MOP_CharacterIndex_t_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_t_] = yes; #local V7 = StandardInvisibleOffset; #local V8 = V2 + V1; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_u_] = object { #local V0 = Height_Lower; MOP_Character [MOP_CharacterIndex_n_] rotate 180 * z translate #declare MOP_CharacterWidth [MOP_CharacterIndex_u_] = MOP_CharacterWidth [MOP_CharacterIndex_n_]; } //object #declare MOP_Character [MOP_CharacterIndex_v_] = object { #local V0 = Height_Lower; #local V_A0 = 60; union { #local V1 = 2 * ComputeCornerLength (180 + V_A0, 0, R, CornerRadius); //Width of flat part #local V_L0 = V0 / sin (radians (V_A0)); #local V2 = V_L0 * cos (radians (V_A0)); #local V_P0 = ; #local V_P1 = V_P0 + ; #local V_P2 = ; sphere {<0, V0, 0>, R} sphere {V_P0, R} sphere {V_P1, R} sphere {V_P2, R} cylinder {<0, V0, 0> V_P0, R} cylinder {V_P0 V_P1, R} cylinder {V_P1 V_P2, R} ArbitraryAngleCornerFiller (V_P0, 180 - V_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (V_P1, 180, V_A0, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_v_] = V_P2.x; } //object #declare MOP_Character [MOP_CharacterIndex_w_] = object { #local V0 = Height_Lower; #local W_A0 = 23; union { #local W1 = 2 * ComputeCornerLength (90 + W_A0, 0, R, CornerRadius); //Width of flat part #local W_L0 = V0 / sin (radians (90 - W_A0)); #local W2 = W_L0 * cos (radians (90 - W_A0)); #local W_P0 = <0, V0, 0>; #local W_P1 = ; #local W_P2 = W_P1 + ; #local W_P3 = ; #local W_P4 = W_P3 + ; #local W_P5 = ; #local W_P6 = W_P5 + ; #local W_P7 = ; sphere {W_P0, R} sphere {W_P1, R} sphere {W_P2, R} sphere {W_P3, R} sphere {W_P4, R} sphere {W_P5, R} sphere {W_P6, R} sphere {W_P7, R} cylinder {W_P0 W_P1, R} cylinder {W_P1 W_P2, R} cylinder {W_P2 W_P3, R} cylinder {W_P3 W_P4, R} cylinder {W_P4 W_P5, R} cylinder {W_P5 W_P6, R} cylinder {W_P6 W_P7, R} ArbitraryAngleCornerFiller (W_P1, 90 + W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P2, 90 - W_A0, 180, R, CornerRadius) ArbitraryAngleCornerFiller (W_P3, 270 - W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P4, 270 + W_A0, 180, R, CornerRadius) ArbitraryAngleCornerFiller (W_P5, 90 + W_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (W_P6, 90 - W_A0, 180, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_w_] = W_P7.x; } //object #declare MOP_Character [MOP_CharacterIndex_x_] = object { #local V0 = Height_Lower; #local X1 = .38; //Vertical #local X2 = .03; //Top vertical offset #local X3 = .1 / R + .05; //CornerRadius multiplier #local X_A0 = 44; #local X_L0_Bottom = X1 / sin (radians (X_A0)); #local X_L0_Top = (V0 - (X1 - X2)) / sin (radians (X_A0)); #local X_P0 = ; #local X_P4 = X_P0 - <0, X2, 0>; #local X_P1 = ; #local X_P2 = ; #local X_P3 = ; #local X_P5 = XPoint (<0, 0, 0>, X_A0, X_P2, -X_A0) #local X_P6 = XPoint (X_P1, 180 - X_A0, X_P3, X_A0) union { sphere {<0, 0, 0>, R} //Bottom left intersection { cylinder {<0, 0, 0> X_P0, R} plane {y, 0 rotate -X_A0 * z translate X_P4} } //intersection sphere {X_P1, R} //Bottom right intersection { cylinder {X_P1 X_P0, R} plane {y, 0 rotate X_A0 * z translate X_P4} } //intersection sphere {X_P2, R} //Top left intersection { cylinder {X_P2 X_P4, R} plane {y, 0 inverse rotate X_A0 * z translate X_P0} } //intersection sphere {X_P3, R} //Top right intersection { cylinder {X_P3 X_P4, R} plane {y, 0 inverse rotate -X_A0 * z translate X_P0} } //intersection #local TCornerRadius = CornerRadius * X3; ArbitraryAngleCornerFiller (X_P0, 180 + X_A0, -X_A0, R, TCornerRadius) //Bottom ArbitraryAngleCornerFiller (X_P4, 180 - X_A0, X_A0, R, TCornerRadius) //Top ArbitraryAngleCornerFiller (X_P5, 180 - X_A0, 180 + X_A0, R, TCornerRadius) //Left ArbitraryAngleCornerFiller (X_P6, X_A0, -X_A0, R, TCornerRadius) //Right } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_x_] = X_P1.x; #declare MOP_InvisibleComponent [MOP_CharacterIndex_x_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_x_] = yes; #local X4 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_y_] = object { #local V0 = Height_Lower; #local A0 = 59; //Left side #local A1 = 62; //Right side #local V1 = sin (radians (90 - A0)) * V0 / sin (radians (A0)); #local V2 = sin (radians (90 - A1)) * V0 / sin (radians (A1)); #local V3 = .2; //Corner radius #local V4 = -.28; //Descender distance (from "g") #local P0 = <-V1, V0, 0>; #local P1 = ; #local P2 = ; #local P3 = <0, -V3, 0>; #local V5 = P2.y + V4 - P3.y; #local V6 = .09; //Extra bottom width #local P4 = <-sin (radians (90 - A1)) * abs (V5) / sin (radians (A1)), V5, 0>; #local P5 = P3 - ; #local yCorner = object { union { ArbitraryRoundCorner (V3, R, 90 - A1, 0, yes) sphere {P2, R} sphere {P3, R} sphere {P5, R} cylinder {P5 P3, R} } //union } //object union { sphere {<0, 0, 0>, R} sphere {P0, R} sphere {P1, R} cylinder {<0, 0, 0> P0, R} cylinder {P4 P1, R} object {yCorner translate P4 - P2} #local TCornerRadius = CornerRadius * 3.5; ArbitraryAngleCornerFiller (<0, 0, 0>, 180 - A0, A1, R, CornerRadius) ArbitraryAngleCornerFiller (<0, 0, 0>, 180 - A0, 180 + A1, R, TCornerRadius) } //union translate V1 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_y_] = V1 + V2; } //object #declare MOP_Character [MOP_CharacterIndex_z_] = object { #local V0 = Height_Lower; #local Z1 = .81; //Width #local Z2 = .03; //Shorten top left #local Z3 = .02; //Shorten top right #local Z_A0 = degrees (atan (V0 / (Z1 - Z3))); #local Z_P0 = ; #local Z_P1 = <0, 0, 0>; #local Z_P2 = ; #local Z_P3 = ; union { ArbitraryHorizontalBar (0, Z1, 0, R) //Bottom bar ArbitraryHorizontalBar (Z2, Z1 - Z3, V0, R) //Top bar cylinder {Z_P1 Z_P2, R} ArbitraryAngleCornerFiller (Z_P1, Z_A0, 0, R, CornerRadius) ArbitraryAngleCornerFiller (Z_P2, 180 + Z_A0, 180, R, CornerRadius) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_z_] = Z1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_z_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_z_] = yes; #local Z4 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_0_] = object { #local V1 = .13; #local V2 = 1.16; //Width #local V3 = .18; #union { GenericClosedCircle_SS (V2, 1, V1, V3, R) #local Dot = object { #local PERIOD1 = R * 2; //Width #local PERIOD2 = PERIOD1 * .8; //Height #local PERIODRadius = R * .075; union { #local PERIODCorner = object { intersection { torus {PERIODRadius, R sturm rotate 90 * x} plane {x, 0} plane {y, 0} } //intersection } //object object {PERIODCorner translate <0, PERIODRadius, 0>} object {PERIODCorner rotate 90 * z translate } object {PERIODCorner rotate 180 * z translate } object {PERIODCorner rotate 270 * z translate <0, PERIOD2, 0>} cylinder {<0, 0, 0> , R} //Bottom cylinder { , R} //Right cylinder {<0, PERIOD2 + PERIODRadius, 0> , R} //Top cylinder {<-PERIODRadius, PERIODRadius, 0> <-PERIODRadius, PERIOD2, 0>, R} //Left cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate <0, PERIODRadius, 0>} cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate } cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate } cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate <0, PERIOD2, 0>} box {<-PERIODRadius, PERIODRadius, -R> } box {<0, 0, -R> } } //union translate PERIODRadius * x translate } //object object {Dot} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_0_] = V2; } //object #declare MOP_Character [MOP_CharacterIndex_1_] = object { #local A0 = 38.5; #local L0 = .53; union { #local V1 = CornerRadius + ComputeCornerLength (0, 180 + A0, R, CornerRadius); //Width of flat part #local P0 = <-V1, 1, 0>; #local P1 = P0 + ; object {VerticalBar} sphere {P0, R} sphere {P1, R} cylinder {P0 <0, 1, 0>, R} cylinder {P1 P0, R} ArbitraryAngleCornerFiller (P0, 180 + A0, 0, R, CornerRadius) RightAngleCornerFiller (QUADRANT3, <0, 1, 0>) } //union translate abs (P1.x) * x #declare MOP_CharacterWidth [MOP_CharacterIndex_1_] = abs (P1.x); } //object #declare MOP_Character [MOP_CharacterIndex_2_] = object { #local V1 = .1; #local V2 = .01; //Offset top #local V3 = .12; #local V4 = .5; //Controls length of top vertical #local V5 = 1.14; //Width #local L0 = .36; #local L1 = 1.12; //Determines width of top portion #local A0 = 5; #local P0 = <0, L0, 0>; #local P1 = P0 + ; union { intersection { sphere_sweep { b_spline 20 <0, -1, 0>, R <0, 0, 0>, R , R , R P0 + , R P0 + <(V1 + V3) * cos (radians (A0)), (V1 + V3) * sin (radians (A0)), 0>, R P1 - <(V1 + V3) * cos (radians (A0)), (V1 + V3) * sin (radians (A0)), 0>, R P1 - , R P1 + <0, V1, 0>, R P1 + <0, V1 + V3, 0>, R , R , R , R , R , R , R , R , R , R , R } //sphere_sweep plane {y, 0 inverse} } //intersection ArbitraryHorizontalBar (0, V5, 0, R) RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_2_] = V5; #declare MOP_InvisibleComponent [MOP_CharacterIndex_2_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_2_] = yes; #local V6 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_3_] = object { #local V1 = .1; #local V1B = .09; #local V2 = 1.12; //Top width #local V3 = .2; #local V3B = .17; #local V4 = .51; //Vertical #local V5 = V2 + .02; //Bottom width #local V6 = .01; //Top offset #local V7 = -.2; //Controls length of middle bar union { sphere_sweep { //Top b_spline 15 , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R } //sphere_sweep sphere_sweep { //Bottom b_spline 15 <0, V1B + V3B + .001, 0>, R <0, V1B + V3B, 0>, R <0, V1B, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R } //sphere_sweep } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_3_] = V5; #declare MOP_InvisibleComponent [MOP_CharacterIndex_3_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_3_] = yes; #local V8 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_4_] = object { #local V2 = 1.2; //Width of lower bar #local A0 = 36; #local L0 = 1.1; union { #local V1 = CornerRadius + ComputeCornerLength (180, 270 + A0, R, CornerRadius); //Width of flat part #local P0 = <-V1, 1, 0>; #local P1 = P0 - ; #local P2 = P1 - <0, V1, 0>; #local P3 = P2 + ; #local P4 = <0, P2.y, 0>; object {VerticalBar} sphere {P0, R} sphere {P1, R} ArbitraryHorizontalBar (P2.x, P3.x, P2.y, R) cylinder {P0 <0, 1, 0>, R} cylinder {P1 P0, R} cylinder {P2 P1, R} #local TCornerRadius = CornerRadius * 1.5; ArbitraryAngleCornerFiller (P0, 0, 180 + A0, R, TCornerRadius) ArbitraryAngleCornerFiller (P1, 270, A0, R, CornerRadius) RightAngleCornerFiller (QUADRANT3, <0, 1, 0>) RightAngleCornerFiller (QUADRANT1, P2) RightAngleCornerFiller (QUADRANT1, P4) RightAngleCornerFiller (QUADRANT2, P4) RightAngleCornerFiller (QUADRANT3, P4) RightAngleCornerFiller (QUADRANT4, P4) } //union translate -P1.x * x #declare MOP_CharacterWidth [MOP_CharacterIndex_4_] = V2; } //object #declare MOP_Character [MOP_CharacterIndex_5_] = object { #local V1 = .12; #local V1B = .11; #local V2 = .22; //Corner radius #local V3 = .2; #local V3B = .15; #local V4 = .645; //Vertical #local V5 = 1.14; //Width #local V6 = .02; //Top left offset #local V7 = V5 - .05; //Top right offset #local V9 = .11; //Y component of corner #local V10 = V4 - V9; //Vertical offset #local A0 = degrees (asin ((V2 - V9) / V2)); #local V11 = sqrt (V2 * V2 - (V2 - V9) * (V2 - V9)); union { ArbitraryHorizontalBar (V6, V7, 1, R) sphere {, R} cylinder { , R} #local DigitCorner = object { #local DigitCornerRadius = V2; intersection { torus {DigitCornerRadius, R sturm rotate 90 * x} plane {x, 0} plane {y, 0 inverse rotate -A0 * z} } //intersection } //object object {DigitCorner translate } sphere {, R} difference { sphere_sweep { b_spline 15 <0, V1B + V3B + .001, 0>, R <0, V1B + V3B, 0>, R <0, V1B, 0>, R , R , R , R , R , R , R , R , R , R , R <0, V4, 0>, R <-1, V4, 0>, R } //sphere_sweep box {<-1, V4 - R - .1, -R - .1> } } //difference RightAngleCornerFiller (QUADRANT4, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_5_] = V5; #declare MOP_InvisibleComponent [MOP_CharacterIndex_5_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_5_] = yes; #local V12 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_7_] = object { #local V1 = 1.16; //Width #local A0 = 49; union { #local V2 = CornerRadius + ComputeCornerLength (180, 270 + A0, R, CornerRadius); //Width of flat part #local V3 = sin (radians (90 - A0)) * (1 - V2) / sin (radians (A0)); ArbitraryHorizontalBar (0, V1, 1, R) #local P0 = ; #local P1 = ; cylinder {P0 , R} sphere {P0, R} sphere {P1, R} cylinder {P1, P0, R} ArbitraryAngleCornerFiller (P0, 180 + A0, 90, R, CornerRadius) RightAngleCornerFiller (QUADRANT3, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_7_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_7_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_7_] = yes; #local V2 = StandardInvisibleOffset; intersection { cylinder { , R} plane {y, 0 inverse rotate A0 * z translate P1.x * x} } //intersection } //object } //object #declare MOP_Character [MOP_CharacterIndex_8_] = object { #local V1 = .1; #local V2 = 1.12; //Width #local V3 = .2; #local V4 = .52; //Vertical #local V5 = .045; //Top offset sphere_sweep { b_spline 35 , R , R <0, V1, 0>, R <0, V1 + V3, 0>, R <0, V4 - V1 - V3, 0>, R <0, V4 - V1, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R <0, V1, 0>, R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_8_] = V2; } //object #declare MOP_Character [MOP_CharacterIndex_9_] = object { #local V1 = .12; #local V1B = .12; #local V2 = 1.1; //Width #local V3 = .2; #local V3B = .12; #local V4 = .45; //Vertical #local V5 = .01; //Bottom offset sphere_sweep { b_spline 26 , R , R , R , R , R , R , R , R , R , R , R , R , R , R , R <0, 1 - V1, 0>, R <0, 1 - V1 - V3, 0>, R <0, V4 + V1 + V3, 0>, R <0, V4 + V1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_9_] = V2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_9_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_9_] = yes; #local V6 = StandardInvisibleOffset; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_6_] = object { object {MOP_Character [MOP_CharacterIndex_9_] translate -MOP_CharacterWidth [MOP_CharacterIndex_9_] * x rotate 180 * z translate 1 * y} #declare MOP_CharacterWidth [MOP_CharacterIndex_6_] = MOP_CharacterWidth [MOP_CharacterIndex_9_]; #declare MOP_InvisibleComponent [MOP_CharacterIndex_6_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_6_] = yes; #local V6 = StandardInvisibleOffset; cylinder { , R translate -MOP_CharacterWidth [MOP_CharacterIndex_9_] * x rotate 180 * z translate 1 * y} } //object } //object #declare MOP_Character [MOP_CharacterIndex_PERIOD_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; union { #local PERIODCorner = object { intersection { torus {PERIODRadius, R sturm rotate 90 * x} plane {x, 0} plane {y, 0} } //intersection } //object object {PERIODCorner translate <0, PERIODRadius, 0>} object {PERIODCorner rotate 90 * z translate } object {PERIODCorner rotate 180 * z translate } object {PERIODCorner rotate 270 * z translate <0, PERIOD2, 0>} cylinder {<0, 0, 0> , R} //Bottom cylinder { , R} //Right cylinder {<0, PERIOD2 + PERIODRadius, 0> , R} //Top cylinder {<-PERIODRadius, PERIODRadius, 0> <-PERIODRadius, PERIOD2, 0>, R} //Left cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate <0, PERIODRadius, 0>} cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate } cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate } cylinder {<0, 0, -R>, <0, 0, R>, PERIODRadius translate <0, PERIOD2, 0>} box {<-PERIODRadius, PERIODRadius, -R> } box {<0, 0, -R> } } //union translate PERIODRadius * x #declare MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_] = PERIOD1 + PERIODRadius; } //object #declare MOP_Character [MOP_CharacterIndex_COMMA_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; #local V1 = R * 1.1; #local A0 = 30; #local CommaTail = object { #local CommaTailRadius = R; union { intersection { torus {CommaTailRadius, R sturm rotate 90 * x} plane {x, 0 rotate A0 * z inverse} plane {y, 0} } //intersection sphere {, R} } //union } //object #local CommaTail = object { union { sphere {, R} cylinder { , R} object {CommaTail translate -V1 * y} } //union } //object union { object {MOP_Character [MOP_CharacterIndex_PERIOD_]} object {CommaTail translate PERIODRadius * x} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_COMMA_] = MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_]; } //object #declare MOP_Character [MOP_CharacterIndex_COLON_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; #local V1 = .6; union { object {MOP_Character [MOP_CharacterIndex_PERIOD_]} object {MOP_Character [MOP_CharacterIndex_PERIOD_] translate V1 * y} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_COLON_] = MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_]; #declare MOP_InvisibleComponent [MOP_CharacterIndex_COLON_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_COLON_] = yes; union { cylinder {<0, 0, 0> <0, V1, 0>, R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_SEMICOLON_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; #local V1 = .6; union { object {MOP_Character [MOP_CharacterIndex_COMMA_]} object {MOP_Character [MOP_CharacterIndex_PERIOD_] translate V1 * y} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_SEMICOLON_] = MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_]; #declare MOP_InvisibleComponent [MOP_CharacterIndex_SEMICOLON_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_SEMICOLON_] = yes; union { cylinder {<0, 0, 0> <0, V1, 0>, R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_APOSTROPHE_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; MOP_Character [MOP_CharacterIndex_COMMA_] translate (1 - PERIOD2 - PERIODRadius) * y #declare MOP_CharacterWidth [MOP_CharacterIndex_APOSTROPHE_] = MOP_CharacterWidth [MOP_CharacterIndex_COMMA_]; } //object #declare MOP_Character [MOP_CharacterIndex_QUOTELeft_] = object { #local PERIOD1 = R * 1; //Width #local PERIOD2 = PERIOD1 * .4; //Height #local PERIODRadius = R * .075; #local V1 = .035; #local V2 = R * sin (radians (270 + 30)) - R * 1.1; //Y offset union { object {MOP_Character [MOP_CharacterIndex_COMMA_] translate (-PERIOD2 - PERIODRadius) * y rotate 180 * z translate } object {MOP_Character [MOP_CharacterIndex_COMMA_] translate (-PERIOD2 - PERIODRadius) * y rotate 180 * z translate } } //union translate (1 - PERIOD2 - PERIODRadius) * y #declare MOP_CharacterWidth [MOP_CharacterIndex_QUOTELeft_] = MOP_CharacterWidth [MOP_CharacterIndex_COMMA_] + R * 3 + V1; } //object #declare MOP_Character [MOP_CharacterIndex_QUOTERight_] = object { #local V1 = .035; union { object {MOP_Character [MOP_CharacterIndex_APOSTROPHE_]} object {MOP_Character [MOP_CharacterIndex_APOSTROPHE_] translate (MOP_CharacterWidth [MOP_CharacterIndex_COMMA_] + R * 2 + V1) * x} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_QUOTERight_] = MOP_CharacterWidth [MOP_CharacterIndex_COMMA_] + R * 3 + V1; } //object #declare MOP_Character [MOP_CharacterIndex_EXCLAMATION_] = object { #local V1 = .292; #local V2 = MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_] / 2; union { object {MOP_Character [MOP_CharacterIndex_PERIOD_]} sphere {, R} sphere {, R} cylinder { , R} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_EXCLAMATION_] = MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_]; #declare MOP_InvisibleComponent [MOP_CharacterIndex_EXCLAMATION_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_EXCLAMATION_] = yes; cylinder { , R} } //object } //object #declare MOP_Character [MOP_CharacterIndex_QUESTION_] = object { #local V1 = .06; #local V2 = .03; #local V1B = .1; #local V1C = .04; #local V3 = .12; #local V3B = .2; #local V3C = .08; #local V4 = -.4; #local V5 = .25; #local A0 = 12; #local L0 = .53; #local P0 = <0, .44, 0>; #local P1 = P0 + ; union { sphere_sweep { b_spline 20 <0, P0.y - V1C - V3C - V2 - .01, 0>, R <0, P0.y - V1C - V3C - V2, 0>, R <0, P0.y - V1C - V3C, 0>, R <0, P0.y - V1C, 0>, R P0 + , R P0 + <(V1 + V3) * cos (radians (A0)), (V1 + V3) * sin (radians (A0)), 0>, R P1 - <(V1 + V3) * cos (radians (A0)), (V1 + V3) * sin (radians (A0)), 0>, R P1 - , R , R , R , R , R , R , R , R , R , R , R , R , R } //sphere_sweep object {MOP_Character [MOP_CharacterIndex_PERIOD_] translate (-MOP_CharacterWidth [MOP_CharacterIndex_PERIOD_] / 2) * x} } //union translate -V4 * x #declare MOP_CharacterWidth [MOP_CharacterIndex_QUESTION_] = P1.x - V4; #declare MOP_InvisibleComponent [MOP_CharacterIndex_QUESTION_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_QUESTION_] = yes; #local V6 = StandardInvisibleOffset; union { cylinder {<-V4, 0, 0> <-V4, .295, 0>, R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_SLASH_] = object { #local V1 = .51; //Width union { sphere {<0, 0, 0>, R} sphere {, R} cylinder {<0, 0, 0> , R} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_SLASH_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_DASH_] = object { #local DASH1 = .6; //Width #local DASH2 = .435; //Vertical, match the "G" ArbitraryHorizontalBar (0, DASH1, DASH2, R) #declare MOP_CharacterWidth [MOP_CharacterIndex_DASH_] = DASH1; } //object #declare MOP_Character [MOP_CharacterIndex_PLUS_] = object { #local V1 = .67; //Width #local V2 = .435; //Vertical, match the "G" union { #local Bar = object {ArbitraryHorizontalBar (0, V1, 0, R)} object {Bar translate V2 * y} object {Bar translate (-V1 / 2) * x rotate 90 * z translate } RightAngleCornerFiller (QUADRANT1, ) RightAngleCornerFiller (QUADRANT2, ) RightAngleCornerFiller (QUADRANT3, ) RightAngleCornerFiller (QUADRANT4, ) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_PLUS_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_EQUALS_] = object { #local V1 = .67; //Width #local V2 = .435; //Vertical, match the "G" #local V3 = .16; //Spacing union { #local Bar = object {ArbitraryHorizontalBar (0, V1, 0, R)} object {Bar translate (V2 - V3) * y} object {Bar translate (V2 + V3) * y} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_EQUALS_] = V1; #declare MOP_InvisibleComponent [MOP_CharacterIndex_EQUALS_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_EQUALS_] = yes; #local V4 = StandardInvisibleOffset; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_DOLLAR_] = object { #local S1 = .08; #local S2 = .96; //Top width #local S3 = .13; #local S4 = .43; //Vertical #local S7 = .025; //Additional bottom width #local S8 = .07; //Top and bottom spacing #local S9 = .49; //Center bar x union { sphere_sweep { b_spline 26 <0, S8 + S1 + S3 + .1, 0>, R <0, S8 + S1 + S3, 0>, R <0, S8 + S1, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R <0, S8 + S4 + S1, 0>, R <0, S8 + S4 + S1 + S3, 0>, R <0, 1 - S8 - S1 - S3, 0>, R <0, 1 - S8 - S1, 0>, R , R , R , R , R , R , R , R } //sphere_sweep sphere {, R} sphere {, R} cylinder { , R} #local CornerAssembly = object { union { RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) RightAngleCornerFiller (QUADRANT2, <0, 0, 0>) RightAngleCornerFiller (QUADRANT3, <0, 0, 0>) RightAngleCornerFiller (QUADRANT4, <0, 0, 0>) } //union } //object object {CornerAssembly translate } object {CornerAssembly translate } object {CornerAssembly translate } } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_DOLLAR_] = S2 + S7; #declare MOP_InvisibleComponent [MOP_CharacterIndex_DOLLAR_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_DOLLAR_] = yes; #local S5 = StandardInvisibleOffset; #local S9 = S2 + .01; union { cylinder { , R} cylinder { , R} } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_PARENTHESISLeft_] = object { #local V1 = .1; #local V2 = .3; //Width #local V3 = .24; sphere_sweep { b_spline 10 , R , R , R <0, V1, 0>, R <0, V1 + V3, 0>, R <0, 1 - V1 - V3, 0>, R <0, 1 - V1, 0>, R , R , R , R } //sphere_sweep #declare MOP_CharacterWidth [MOP_CharacterIndex_PARENTHESISLeft_] = V2 - .007; } //object #declare MOP_Character [MOP_CharacterIndex_PARENTHESISRight_] = object { MOP_Character [MOP_CharacterIndex_PARENTHESISLeft_] translate -MOP_CharacterWidth [MOP_CharacterIndex_PARENTHESISLeft_] * x rotate 180 * y #declare MOP_CharacterWidth [MOP_CharacterIndex_PARENTHESISRight_] = MOP_CharacterWidth [MOP_CharacterIndex_PARENTHESISLeft_]; } //object #declare MOP_Character [MOP_CharacterIndex_SQUAREBRACKETLeft_] = object { #local V1 = .28; union { ArbitraryHorizontalBar (0, V1, 0, R) ArbitraryHorizontalBar (0, V1, 1, R) cylinder {<0, 0, 0> <0, 1, 0>, R} RightAngleCornerFiller (QUADRANT1, <0, 0, 0>) RightAngleCornerFiller (QUADRANT4, <0, 1, 0>) } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_SQUAREBRACKETLeft_] = V1; } //object #declare MOP_Character [MOP_CharacterIndex_SQUAREBRACKETRight_] = object { MOP_Character [MOP_CharacterIndex_SQUAREBRACKETLeft_] translate -MOP_CharacterWidth [MOP_CharacterIndex_SQUAREBRACKETLeft_] * x rotate 180 * y #declare MOP_CharacterWidth [MOP_CharacterIndex_SQUAREBRACKETRight_] = MOP_CharacterWidth [MOP_CharacterIndex_SQUAREBRACKETLeft_]; } //object #declare MOP_Character [MOP_CharacterIndex_ANGLEBRACKETLeft_] = object { #local V1 = .435; //Vertical, match the "G" #local L0 = .74; #local A0 = 24; #local P0 = ; union { sphere {<0, P0.y, 0>, R} sphere {, R} sphere {, R} cylinder {<0, P0.y, 0> , R} cylinder {<0, P0.y, 0> , R} ArbitraryAngleCornerFiller (<0, P0.y, 0>, A0, 360 - A0, R, CornerRadius) } //union translate (V1 - P0.y) * y #declare MOP_CharacterWidth [MOP_CharacterIndex_ANGLEBRACKETLeft_] = P0.x; #declare MOP_InvisibleComponent [MOP_CharacterIndex_ANGLEBRACKETLeft_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_ANGLEBRACKETLeft_] = yes; #local V2 = StandardInvisibleOffset; intersection { cylinder { , R} plane {y, 0 rotate A0 * z translate V1 * y} plane {y, 0 inverse rotate -A0 * z translate V1 * y} } //intersection } //object } //object #declare MOP_Character [MOP_CharacterIndex_ANGLEBRACKETRight_] = object { MOP_Character [MOP_CharacterIndex_ANGLEBRACKETLeft_] translate -MOP_CharacterWidth [MOP_CharacterIndex_ANGLEBRACKETLeft_] * x rotate 180 * y #declare MOP_CharacterWidth [MOP_CharacterIndex_ANGLEBRACKETRight_] = MOP_CharacterWidth [MOP_CharacterIndex_ANGLEBRACKETLeft_]; #declare MOP_InvisibleComponent [MOP_CharacterIndex_ANGLEBRACKETRight_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_ANGLEBRACKETRight_] = yes; MOP_InvisibleComponent [MOP_CharacterIndex_ANGLEBRACKETLeft_] translate -MOP_CharacterWidth [MOP_CharacterIndex_ANGLEBRACKETLeft_] * x rotate 180 * y } //object } //object #declare MOP_Character [MOP_CharacterIndex_PERCENT_] = object { #local V1 = .07; #local V2 = .7; //Width of circle #local V3 = .12; #local V4 = .62; //Height of circle #local V5 = .34; //Width of slash #local V6 = .75; union { #local Circle = object {GenericClosedCircle_SS (V2, V4, V1, V3, R)} #local Slash = object { union { sphere {<0, 0, 0>, R} sphere {, R} cylinder {<0, 0, 0> , R} } //union } //object object {Circle translate (1 - V4) * y} object {Circle translate (V6 + V5 + V6 - V2) * x} object {Slash translate V6 * x} } //union #declare MOP_CharacterWidth [MOP_CharacterIndex_PERCENT_] = V6 + V5 + V6; } //object #declare MOP_Character [MOP_CharacterIndex_NUMBER_] = object { #local A0 = 82.5; #local L0 = 1 / sin (radians (A0)); #local V1 = .165; //Polar distance from vertical center for crossbars #local V2 = .5; //Distance apart for diagonal bars #local V3 = .09 + R; //Distance horizontal bars extend past diagonal bars #local P0 = ; #local P1 = P0 - ; #local P2 = P0 + ; #local P3 = P1 + ; #local P4 = P2 + ; union { #local DiagonalBar = object { union { sphere {<0, 0, 0>, R} sphere {, R} cylinder {<0, 0, 0> , R} } //union rotate A0 * z } //object #local HorizontalBar = object {ArbitraryHorizontalBar (0, V3 + V2 + V3, 0, R)} object {DiagonalBar} object {DiagonalBar translate V2 * x} object {HorizontalBar translate P1 - } object {HorizontalBar translate P2 - } #local CornerAssembly = object { union { ArbitraryAngleCornerFiller (<0, 0, 0>, 0, A0, R, CornerRadius) ArbitraryAngleCornerFiller (<0, 0, 0>, 0, A0 + 180, R, CornerRadius) ArbitraryAngleCornerFiller (<0, 0, 0>, 180, A0, R, CornerRadius) ArbitraryAngleCornerFiller (<0, 0, 0>, 180, A0 + 180, R, CornerRadius) } //union } //object object {CornerAssembly translate P1} object {CornerAssembly translate P2} object {CornerAssembly translate P3} object {CornerAssembly translate P4} } //union translate (-P1.x + V3) * x #declare MOP_CharacterWidth [MOP_CharacterIndex_NUMBER_] = -P1.x + V3 + P4.x + V3; } //object #declare MOP_Character [MOP_CharacterIndex_ASTERISK_] = object { #local L0 = R + .22; #local V1 = L0 * sin (radians (60)); #local CenterRadius = sin (radians (60)) * R / sin (radians (30)) - R * 1.25; difference { union { #local Bar = object { union { sphere {, R} cylinder {<0, 0, 0> , R} } //union } //object sphere {<0, 0, 0>, R} #for (I, 0, 5) object {Bar rotate (I * 60) * z} ArbitraryAngleCornerFiller (<0, 0, 0>, I * 60, (I + 1) * 60, R, CornerRadius) #end //#for } //union #local Cutout = object { difference { cylinder {<0, 0, -R - .1> <0, 0, 0>, CenterRadius + R} torus {CenterRadius + R, R sturm rotate 90 * x} } //difference } //object object {Cutout} object {Cutout rotate 180 * x} cylinder {<0, 0, -R - .1> <0, 0, R + .1>, CenterRadius} } //difference translate #declare MOP_CharacterWidth [MOP_CharacterIndex_ASTERISK_] = L0 * 2; #declare MOP_InvisibleComponent [MOP_CharacterIndex_ASTERISK_] = object { #declare MOP_IncludeInvisibleComponent [MOP_CharacterIndex_ASTERISK_] = yes; union { #for (I, 0, 5) cylinder { , R rotate (I * 60) * z translate } #end //#for } //union } //object } //object #declare MOP_Character [MOP_CharacterIndex_AT_] = object { #local V1 = 15; //Degrees #local V2 = .5104; //Outer radius adjustment (for 20 degrees) #local V2 = .5058; //Outer radius adjustment (for 15 degrees) #local V3 = .4; //Inner width #local V4 = .5; //Inner height #local V5 = .09; #local V6 = .1; #local V7 = .03; //X rounding factor #local V8 = .015; //Y rounding factor #local V9 = -V3 / 2 - .02; //Center X offset #local V10 = -V4 / 2 - .03; //Center Y offset #local V11 = .12; //Vertical offset for tail #local V12 = 5; //Angle offset union { sphere_sweep { //Center b_spline 19 , R , R <0, V5, 0>, R <0 - V7, V5 + V6, 0>, R <0 - V7, V4 - V5 - V6, 0>, R <0, V4 - V5, 0>, R , R , R , R , R , R , R , R , R , R , R , R , R <0, V5, 0>, R translate } //sphere_sweep sphere_sweep { //Outer b_spline 360 / V1 - 0 + 4 , R , R , R , R , R , R #for (I, 0, 360 - V1 * 3, V1) , R #end //#for translate } //sphere_sweep } //union rotate -15 * z translate <.5, .5, 0> #declare MOP_CharacterWidth [MOP_CharacterIndex_AT_] = 1; } //object #declare MOP_Character [MOP_CharacterIndex_SMILEY_] = object { #local V1 = .02; //Eye radius #local V2 = .1; //Eye height #switch (R) //Adjust eye spacing #range (0, .02) #local V3 = .16; #break #range (.02, .06) #local V3 = -2.5 * R + .21; #break #range (.06, 999) #local V3 = .06; #break #end //#switch #local V4 = .08; //Eye y offset #local V5 = .32; //Mouth radius #local V6 = .3; //Mouth y offset #local A0 = 70; union { torus {.5, R sturm rotate 90 * x} #local Mouth = object { union { intersection { torus {V5, R sturm rotate 90 * x} plane {x, 0 inverse rotate -A0 * z} plane {x, 0 rotate A0 * z} } //intersection sphere {, R} sphere {, R} } //union translate (V5 - V6) * y } //object object {Mouth} #local Eye = object { union { intersection { torus {V1, R sturm rotate 90 * x} plane {y, 0} } //intersection intersection { torus {V1, R sturm rotate 90 * x translate V2 * y} plane {y, V2 inverse} } //intersection sphere {<-V1, 0, 0>, R} sphere {<-V1, V2, 0>, R} sphere {, R} sphere {, R} cylinder {<-V1, 0, 0> <-V1, V2, 0>, R} cylinder { , R} cylinder {<0, 0, -R> <0, 0, R>, V1} cylinder {<0, V2, -R> <0, V2, R>, V1} box {<-V1, 0, -R> } } //union } //object object {Eye translate <-V1 - R - V3 / 2, V4, 0>} object {Eye translate } } //union translate <.5, .5, 0> #declare MOP_CharacterWidth [MOP_CharacterIndex_SMILEY_] = 1; } //object #declare LastMOP_FontRadius = MOP_FontRadius; #declare MOP_CharactersValid = yes; #end //#macro CreateMOP_Characters #macro TextToIndex (Character) #switch (asc (Character)) #case (asc (" ")) #local IndexValue = MOP_CharacterIndex_SPACE_; #break #case (asc ("\"")) #local IndexValue = MOP_CharacterIndex_QUOTE_; #break #range (asc ("A"), asc ("Z")) #local IndexValue = asc (Character) - asc ("A"); #break #range (asc ("a"), asc ("z")) #local IndexValue = asc (Character) - asc ("a") + 26; #break #range (asc ("0"), asc ("9")) #local IndexValue = asc (Character) - asc ("0") + 52; #break #case (asc (".")) #local IndexValue = MOP_CharacterIndex_PERIOD_; #break #case (asc (",")) #local IndexValue = MOP_CharacterIndex_COMMA_; #break #case (asc (":")) #local IndexValue = MOP_CharacterIndex_COLON_; #break #case (asc (";")) #local IndexValue = MOP_CharacterIndex_SEMICOLON_; #break #case (asc ("'")) #local IndexValue = MOP_CharacterIndex_APOSTROPHE_; #break #case (asc ("!")) #local IndexValue = MOP_CharacterIndex_EXCLAMATION_; #break #case (asc ("?")) #local IndexValue = MOP_CharacterIndex_QUESTION_; #break #case (asc ("/")) #local IndexValue = MOP_CharacterIndex_SLASH_; #break #case (asc ("-")) #local IndexValue = MOP_CharacterIndex_DASH_; #break #case (asc ("+")) #local IndexValue = MOP_CharacterIndex_PLUS_; #break #case (asc ("=")) #local IndexValue = MOP_CharacterIndex_EQUALS_; #break #case (asc ("$")) #local IndexValue = MOP_CharacterIndex_DOLLAR_; #break #case (asc ("(")) #local IndexValue = MOP_CharacterIndex_PARENTHESISLeft_; #break #case (asc (")")) #local IndexValue = MOP_CharacterIndex_PARENTHESISRight_; #break #case (asc ("[")) #local IndexValue = MOP_CharacterIndex_SQUAREBRACKETLeft_; #break #case (asc ("]")) #local IndexValue = MOP_CharacterIndex_SQUAREBRACKETRight_; #break #case (asc ("<")) #local IndexValue = MOP_CharacterIndex_ANGLEBRACKETLeft_; #break #case (asc (">")) #local IndexValue = MOP_CharacterIndex_ANGLEBRACKETRight_; #break #case (asc ("%")) #local IndexValue = MOP_CharacterIndex_PERCENT_; #break #case (asc ("#")) #local IndexValue = MOP_CharacterIndex_NUMBER_; #break #case (asc ("*")) #local IndexValue = MOP_CharacterIndex_ASTERISK_; #break #case (asc ("@")) #local IndexValue = MOP_CharacterIndex_AT_; #break #case (asc ("~")) #local IndexValue = MOP_CharacterIndex_SMILEY_; #break #else //Undefined character #local IndexValue = -1; #break #end //#switch IndexValue #end //#macro TextToIndex #macro CreateMOP_TextObject (TextLine_, MOP_Gap_, MOP_Space_, MOP_FontRadius_, MOP_ApplyKerning_) #declare MOP_Gap = MOP_Gap_; #declare MOP_Space = MOP_Space_; #declare MOP_FontRadius = MOP_FontRadius_; #declare MOP_ApplyKerning = MOP_ApplyKerning_; #if (MOP_FontRadius <= 0) #error "MOPFont Message: MOP_FontRadius must be > 0." #end //#if #if (MOP_FontRadius != LastMOP_FontRadius) CreateMOP_Characters (MOP_FontRadius) #end //#if #local TextLine = TextLine_; #local TextLine_ = ""; #for (I, 1, strlen (TextLine)) #local CurrentCharacter = substr (TextLine, I, 1); #if (TextToIndex (CurrentCharacter) != -1) #local TextLine_ = concat (TextLine_, CurrentCharacter); #else #debug "\nMOPFont Message: A non-supported character was skipped.\n" #end //#if #end //#for #local TextLine = TextLine_; #if (TextLine = "") #error "MOPFont Message: No valid characters." #end //#if #while (substr (TextLine, 1, 1) = " ") //Remove leading spaces #if (strlen (TextLine) > 1) #local TextLine = substr (TextLine, 2, strlen (TextLine) - 1); #else #error "MOPFont Message: No valid characters." #end //#if #end //#while #while (substr (TextLine, strlen (TextLine), 1) = " ") //Remove trailing spaces #local TextLine = substr (TextLine, 1, strlen (TextLine) - 1); #end //#while #local LineCharacterIndex = array [strlen (TextLine)] #local NLineCharacters = 0; #local NextQuote = MOP_CharacterIndex_QUOTELeft_; #for (I, 1, strlen (TextLine)) #local CurrentLineCharacterIndex = TextToIndex (substr (TextLine, I, 1)); #if (CurrentLineCharacterIndex != MOP_CharacterIndex_SPACE_) #if (CurrentLineCharacterIndex = MOP_CharacterIndex_QUOTE_) #switch (NextQuote) #case (MOP_CharacterIndex_QUOTELeft_) #local CurrentLineCharacterIndex = MOP_CharacterIndex_QUOTELeft_; #local NextQuote = MOP_CharacterIndex_QUOTERight_; #break #case (MOP_CharacterIndex_QUOTERight_) #local CurrentLineCharacterIndex = MOP_CharacterIndex_QUOTERight_; #local NextQuote = MOP_CharacterIndex_QUOTELeft_; #break #end //#switch #end //#if #local LineCharacterIndex [NLineCharacters] = CurrentLineCharacterIndex; #local NLineCharacters = NLineCharacters + 1; #end //#if #end //#for #if (NLineCharacters = 0) #error "MOPFont Message: No valid characters." #end //#if #if (NLineCharacters > 1 & MOP_ApplyKerning) #local MaximumKerningDistance = 999; #local Range_Lower = -.28; #local Range_Upper = 1; #local NSteps = 600; //More steps produce more accuracy but take more time. #local CharacterInUse = array [NDefinedCharacters] #declare CharacterFullVertical = array [NDefinedCharacters] #local Kerning = array [NDefinedCharacters] [NDefinedCharacters] #declare SideDistance_Left = array [NDefinedCharacters] [NSteps] #declare SideDistance_Right = array [NDefinedCharacters] [NSteps] #local CharacterIndex_Save = array [NLineCharacters] #local CurrentX_Save = array [NLineCharacters] #for (I, 0, NDefinedCharacters - 1) //Initialize kerning flags #local CharacterInUse [I] = no; #declare CharacterFullVertical [I] = yes; #for (J, 0, NDefinedCharacters - 1) #local Kerning [I] [J] = 0; #end //#for #end //#for #for (I, 0, NLineCharacters - 1) #local CharacterInUse [LineCharacterIndex [I]] = yes; //Flag for character measurement #end //#for #for (I, 0, NDefinedCharacters - 1) #if (CharacterInUse [I]) #if (MOP_IncludeInvisibleComponent [I]) #local CurrentShape = object { union { object {MOP_Character [I]} object {MOP_InvisibleComponent [I]} } //union } //object #else #local CurrentShape = object {MOP_Character [I]} #end //#if MeasureCharacter (I, object {CurrentShape translate }, Range_Lower, Range_Upper, NSteps) #end //#if #end //#for #for (I, 1, NLineCharacters - 1) #local Kerning [LineCharacterIndex [I - 1]] [LineCharacterIndex [I]] = -1; //Flag for character-to-character measurement #if (I >= 2) #if (!CharacterFullVertical [LineCharacterIndex [I - 1]]) #local Kerning [LineCharacterIndex [I - 2]] [LineCharacterIndex [I]] = -1; #end //#if #end //#if #end //#for #for (I, 0, NDefinedCharacters - 1) #for (J, 0, NDefinedCharacters - 1) #if (Kerning [I] [J] = -1) //Flagged for measurement #local CurrentKerningValue = MeasureCharacterToCharacter (I, J, Range_Lower, Range_Upper, NSteps) #if (CurrentKerningValue = -1) //Characters never touch #local Kerning [I] [J] = DefaultKerningDistance; #else #if (J = MOP_CharacterIndex_APOSTROPHE_ | J = MOP_CharacterIndex_QUOTELeft_ | J = MOP_CharacterIndex_QUOTERight_) #local Kerning [I] [J] = min (CurrentKerningValue, DefaultKerningDistance); #else #local Kerning [I] [J] = min (CurrentKerningValue, MaximumKerningDistance); #end //#if #end //#if //#debug concat ("\nMOPFont Message: Kerning value for characters ", str (I, 0, 0), " and ", str (J, 0, 0), ": ", str (Kerning [I] [J], 0, 3), "\n") #end //#if #end //#for #end //#for #end //#if #declare MOP_TextObject = object { #local NextQuote = MOP_CharacterIndex_QUOTELeft_; #local CurrentX = 0; #local MaximumX = 0; #local NVisibleCharacters = 0; #if (NLineCharacters > 1) union { #for (I, 1, strlen (TextLine)) #local CurrentCharacterIndex = TextToIndex (substr (TextLine, I, 1)); #if (CurrentCharacterIndex = MOP_CharacterIndex_SPACE_) #local CurrentX = CurrentX + MOP_Space; #else #if (CurrentCharacterIndex = MOP_CharacterIndex_QUOTE_) #switch (NextQuote) #case (MOP_CharacterIndex_QUOTELeft_) #local CurrentCharacterIndex = MOP_CharacterIndex_QUOTELeft_; #local NextQuote = MOP_CharacterIndex_QUOTERight_; #break #case (MOP_CharacterIndex_QUOTERight_) #local CurrentCharacterIndex = MOP_CharacterIndex_QUOTERight_; #local NextQuote = MOP_CharacterIndex_QUOTELeft_; #break #end //#switch #end //#if #if (MOP_ApplyKerning) #if (NVisibleCharacters >= 2) #if (!CharacterFullVertical [CharacterIndex_Save [NVisibleCharacters - 1]]) #local CurrentX2 = CurrentX_Save [NVisibleCharacters - 2] + MOP_CharacterWidth [CharacterIndex_Save [NVisibleCharacters - 2]] + MOP_FontRadius * 2 + MOP_Gap; #local CurrentX2 = CurrentX2 - Kerning [CharacterIndex_Save [NVisibleCharacters - 2]] [CurrentCharacterIndex]; #local CurrentX = max (CurrentX, CurrentX2); #end //#if #end //#if #local CharacterIndex_Save [NVisibleCharacters] = CurrentCharacterIndex; //Contains correct quote indices #local CurrentX_Save [NVisibleCharacters] = CurrentX; #local NVisibleCharacters = NVisibleCharacters + 1; #end //#if object {MOP_Character [CurrentCharacterIndex] translate CurrentX * x} #local CurrentX = CurrentX + MOP_CharacterWidth [CurrentCharacterIndex] + MOP_FontRadius * 2 + MOP_Gap; #local MaximumX = max (CurrentX, MaximumX); #if (MOP_ApplyKerning) #if (I < strlen (TextLine)) #for (J, I + 1, strlen (TextLine)) #local NextCharacterIndex = TextToIndex (substr (TextLine, J, 1)); #if (NextCharacterIndex != MOP_CharacterIndex_SPACE_) //Use this one #if (NextCharacterIndex = MOP_CharacterIndex_QUOTE_) #switch (NextQuote) #case (MOP_CharacterIndex_QUOTELeft_) #local NextCharacterIndex = MOP_CharacterIndex_QUOTELeft_; #break #case (MOP_CharacterIndex_QUOTERight_) #local NextCharacterIndex = MOP_CharacterIndex_QUOTERight_; #break #end //#switch #end //#if #break #end //#if #end //#for #local CurrentX = CurrentX - Kerning [CurrentCharacterIndex] [NextCharacterIndex]; #local CurrentX = max (CurrentX, 0); //Allow for ".T" (for example) - the "T" would be moved to x < 0 #end //#if #end //#if #end //#if #end //#for } //union #else #local CurrentCharacterIndex = TextToIndex (TextLine); #if (CurrentCharacterIndex = MOP_CharacterIndex_QUOTE_) #local CurrentCharacterIndex = NextQuote; #end //#if object {MOP_Character [CurrentCharacterIndex]} #local MaximumX = MOP_CharacterWidth [CurrentCharacterIndex] + MOP_FontRadius * 2 + MOP_Gap; #end //#if translate //The lower left corner/back of the text object will be at the origin. #local S = 1 / (1 + MOP_FontRadius * 2); scale } //object #declare MOP_TextObjectWidth = (MaximumX - MOP_Gap) * S; #end //#macro CreateMOP_TextObject /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * */ /* * INITIALIZATIONS * */ /* * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #declare DefaultKerningDistance = .12; //Default value when characters never touch or one goes "inside" another one #declare MOP_CharacterIndex_SPACE_ = 999; #declare MOP_CharacterIndex_QUOTE_ = 998; #declare MOP_CharacterIndex_A_ = 0; #declare MOP_CharacterIndex_B_ = 1; #declare MOP_CharacterIndex_C_ = 2; #declare MOP_CharacterIndex_D_ = 3; #declare MOP_CharacterIndex_E_ = 4; #declare MOP_CharacterIndex_F_ = 5; #declare MOP_CharacterIndex_G_ = 6; #declare MOP_CharacterIndex_H_ = 7; #declare MOP_CharacterIndex_I_ = 8; #declare MOP_CharacterIndex_J_ = 9; #declare MOP_CharacterIndex_K_ = 10; #declare MOP_CharacterIndex_L_ = 11; #declare MOP_CharacterIndex_M_ = 12; #declare MOP_CharacterIndex_N_ = 13; #declare MOP_CharacterIndex_O_ = 14; #declare MOP_CharacterIndex_P_ = 15; #declare MOP_CharacterIndex_Q_ = 16; #declare MOP_CharacterIndex_R_ = 17; #declare MOP_CharacterIndex_S_ = 18; #declare MOP_CharacterIndex_T_ = 19; #declare MOP_CharacterIndex_U_ = 20; #declare MOP_CharacterIndex_V_ = 21; #declare MOP_CharacterIndex_W_ = 22; #declare MOP_CharacterIndex_X_ = 23; #declare MOP_CharacterIndex_Y_ = 24; #declare MOP_CharacterIndex_Z_ = 25; #declare MOP_CharacterIndex_a_ = 26; #declare MOP_CharacterIndex_b_ = 27; #declare MOP_CharacterIndex_c_ = 28; #declare MOP_CharacterIndex_d_ = 29; #declare MOP_CharacterIndex_e_ = 30; #declare MOP_CharacterIndex_f_ = 31; #declare MOP_CharacterIndex_g_ = 32; #declare MOP_CharacterIndex_h_ = 33; #declare MOP_CharacterIndex_i_ = 34; #declare MOP_CharacterIndex_j_ = 35; #declare MOP_CharacterIndex_k_ = 36; #declare MOP_CharacterIndex_l_ = 37; #declare MOP_CharacterIndex_m_ = 38; #declare MOP_CharacterIndex_n_ = 39; #declare MOP_CharacterIndex_o_ = 40; #declare MOP_CharacterIndex_p_ = 41; #declare MOP_CharacterIndex_q_ = 42; #declare MOP_CharacterIndex_r_ = 43; #declare MOP_CharacterIndex_s_ = 44; #declare MOP_CharacterIndex_t_ = 45; #declare MOP_CharacterIndex_u_ = 46; #declare MOP_CharacterIndex_v_ = 47; #declare MOP_CharacterIndex_w_ = 48; #declare MOP_CharacterIndex_x_ = 49; #declare MOP_CharacterIndex_y_ = 50; #declare MOP_CharacterIndex_z_ = 51; #declare MOP_CharacterIndex_0_ = 52; #declare MOP_CharacterIndex_1_ = 53; #declare MOP_CharacterIndex_2_ = 54; #declare MOP_CharacterIndex_3_ = 55; #declare MOP_CharacterIndex_4_ = 56; #declare MOP_CharacterIndex_5_ = 57; #declare MOP_CharacterIndex_6_ = 58; #declare MOP_CharacterIndex_7_ = 59; #declare MOP_CharacterIndex_8_ = 60; #declare MOP_CharacterIndex_9_ = 61; #declare MOP_CharacterIndex_PERIOD_ = 62; #declare MOP_CharacterIndex_COMMA_ = 63; #declare MOP_CharacterIndex_COLON_ = 64; #declare MOP_CharacterIndex_SEMICOLON_ = 65; #declare MOP_CharacterIndex_APOSTROPHE_ = 66; #declare MOP_CharacterIndex_QUOTELeft_ = 67; #declare MOP_CharacterIndex_QUOTERight_ = 68; #declare MOP_CharacterIndex_EXCLAMATION_ = 69; #declare MOP_CharacterIndex_QUESTION_ = 70; #declare MOP_CharacterIndex_SLASH_ = 71; #declare MOP_CharacterIndex_DASH_ = 72; #declare MOP_CharacterIndex_PLUS_ = 73; #declare MOP_CharacterIndex_EQUALS_ = 74; #declare MOP_CharacterIndex_DOLLAR_ = 75; #declare MOP_CharacterIndex_PARENTHESISLeft_ = 76; #declare MOP_CharacterIndex_PARENTHESISRight_ = 77; #declare MOP_CharacterIndex_SQUAREBRACKETLeft_ = 78; #declare MOP_CharacterIndex_SQUAREBRACKETRight_ = 79; #declare MOP_CharacterIndex_ANGLEBRACKETLeft_ = 80; #declare MOP_CharacterIndex_ANGLEBRACKETRight_ = 81; #declare MOP_CharacterIndex_PERCENT_ = 82; #declare MOP_CharacterIndex_NUMBER_ = 83; #declare MOP_CharacterIndex_ASTERISK_ = 84; #declare MOP_CharacterIndex_AT_ = 85; #declare MOP_CharacterIndex_SMILEY_ = 86; #declare NDefinedCharacters = 87; #declare MOP_Character = array [NDefinedCharacters]; #declare MOP_CharacterWidth = array [NDefinedCharacters]; #declare MOP_IncludeInvisibleComponent = array [NDefinedCharacters]; #declare MOP_InvisibleComponent = array [NDefinedCharacters]; #ifndef (MOP_Gap) #declare MOP_Gap = .14; #end #ifndef (MOP_Space) #declare MOP_Space = .65; #end #ifndef (MOP_ApplyKerning) #declare MOP_ApplyKerning = yes; #end #ifndef (MOP_CharactersValid) #declare MOP_CharactersValid = no; #end #declare LastMOP_FontRadius = -1; #if (!MOP_CharactersValid) #ifndef (MOP_FontRadius) #declare MOP_FontRadius = .0625; #end //#ifndef CreateMOP_Characters (MOP_FontRadius) #end //#if