class WoodenBlock : AbstractModel() { // The name of the piece. These are the names which look a little like // the shape. They are NOT the letters that appear on the blocks. // Values ALL 1 2 3 V A I O E Y U S D P R T N L H B X W K J G M F C // See rename @Custom var piece = "1" // The size of the cube @Custom var size = 20 // Make the pieces slightly smaller, so that they fit together. @Custom var gap = 0.3 @Custom var radius = 2 // 1 for a chamfer, more than 1 for more rounding. @Custom var radiusSides = 3 @Custom var embossDepth = 1.2 @Custom var embossThicker = 0.2 // We want a "sphere", whose shadow is the same from either X, Y or Z direction. // A "normal" sphere won't do, as we cannot control the "sides" in the x, y and z. // So here we revolve a semi circle, where the number of sides of the semicircle // and number of sides of the revolution are the same. fun rounding() : Shape3d { //return Sphere( radius, radiusSides ) // A normal sphere won't do! return PolygonBuilder().apply { moveTo(0,-radius) lineTo(radius,-radius) lineTo(radius,radius) lineTo(0,radius) close() }.build() .roundCorner(2, radius, radiusSides ) .roundCorner(1, radius, radiusSides ) .revolve().sides(radiusSides*4) } // ghi // def // abc fun voxel( position: char ) : Shape3d { val lower = position.toLowerCase() val i = lower.toInt() - 'a'.toInt() val x = i % 3 val y = i ~/ 3 val z = if (position.isLowerCase()) 0 else 1 return Cube(size - gap - radius*2).translate( x*size, y*size, z*size ) } fun piece( info : String, color: String, letter : String ) : Shape3d { val pieces = listOf() for (item in info.split(" ")) { val fromC = item.charAt(0) val toC = item.charAt(1) pieces.add( voxel(fromC).hull( voxel(toC ) ) ) 1 } val union = Union3d( pieces ) val result = union.minkowski( rounding() ).translate(radius, radius, radius ) val emboss = Text( letter, size * 0.65 ).hAlign(CENTER) .mirrorX() .offset( embossThicker ) .extrude( embossDepth ) .translate(size*1.5,size*0.2,-0.1) return result.color( color ) - emboss.color("White") } // ghi // def // abc fun piece( name : String ) : Shape3d { val small = "Silver" val four = "Red" val five = "Orange" val extra1 = "Yellow" val extra2 = "Green" if (name == "1") return piece( "bb", small, name ) if (name == "2") return piece( "ab", small, name ) if (name == "3") return piece( "ac", small, name ) if (name == "v") return piece( "ab be", small, name ) if (name == "A") return piece( "be ef fF", four, name ) if (name == "I") return piece( "ab be eE", four, name ) if (name == "O") return piece( "ab be ed da", four, name ) if (name == "E") return piece( "ac cf", four, name ) if (name == "Y") return piece( "ab be ef", four, name ) if (name == "U") return piece( "ac be", four, name ) if (name == "S") return piece( "ab ad aA", four, name ) if (name == "D") return piece( "cb be eE ED", five, name ) if (name == "R") return piece( "ac ad dD", five, name ) if (name == "P") return piece( "ac cf fF", five, name ) if (name == "T") return piece( "ca aA be", five, name ) if (name == "N") return piece( "ab be eE EF", five, name ) if (name == "L") return piece( "ca cC be", five, name ) if (name == "K") return piece( "df dg be", extra1, name ) if (name == "B") return piece( "ac de ad be", extra1, name ) if (name == "H") return piece( "bh df", extra1, name ) if (name == "W") return piece( "ac be bB", extra1, name ) if (name == "C") return piece( "da ac cf", extra1, name ) if (name == "J") return piece( "aA ac cf", extra2, name ) if (name == "G") return piece( "da ac cC", extra2, name ) if (name == "Z") return piece( "ab bh hi", extra2, name ) if (name == "M") return piece( "ab ad de eb aA", extra2, name ) if (name == "F") return piece( "ac cC cf", extra2, name ) return piece( "aa", "Silver", "." ) } override fun build() = piece( piece ) }