|
|
Here's my "Total Overkill" code for calculating position of corners for
a bevelled box.
This is a reply to Greg M. Johnson's post "truncated cubes" to
povray.binaries.images 6. October:
news://news.povray.org/39DDC1B9.8637A48C%40my-dejanews.com
news://news.povray.org/39E1B9BD.60A199EA%40my-dejanews.com
Note: This code does not bevel any convex shape of plane intersections.
(But some of the macros below could be useful when writing code that
does this.)
Tor Olav
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Copyright 2000 by Tor Olav Kristensen
// mailto:tor### [at] hotmailcom
// http://www.crosswinds.net/~tok/tokrays.html
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
#version 3.1;
#include "colors.inc"
global_settings { ambient_light color White }
#declare infinite = 100000;
#declare nothing = 1/infinite;
#declare less = -nothing;
#declare more = +nothing;
//#declare smaller = 1 + less;
//#declare bigger = 1 + more;
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// The macros that do the "dirty" work
// Scalar Triple Product of 3 vectors
#macro S3Prod(v1, v2, v3)
vdot(v1, vcross(v2, v3))
#end // macro S3Prod
// Find the intersection of 3 planes
#macro pl2pl2pl(pPlane1, vPlane1, pPlane2, vPlane2, pPlane3, vPlane3)
((vdot(pPlane1, vPlane1)*vcross(vPlane2, vPlane3) +
vdot(pPlane2, vPlane2)*vcross(vPlane3, vPlane1) +
vdot(pPlane3, vPlane3)*vcross(vPlane1, vPlane2))/
S3Prod(vPlane1, vPlane2, vPlane3))
#end // macro pl2pl2pl
// Make a convex shape by intersection of planes
#macro MakeConvex(PlaneNormals, PlaneDistances)
#local NrOfPlanes = dimension_size(PlaneNormals, 1);
#local PlaneCnt = 0;
intersection {
#while (PlaneCnt < NrOfPlanes)
plane { PlaneNormals[PlaneCnt], PlaneDistances[PlaneCnt] }
#local PlaneCnt = PlaneCnt + 1;
#end // while
}
#end // macro MakeConvex
// Determine if there are any planes between a point and origo
#macro PlaneUnder(p0, PlaneNormals, PlaneDistances)
#local NrOfPlanes = dimension_size(PlaneNormals, 1);
#local PointDist = vlength(p0);
#local CloserPlane = false;
#local Cnt = 0;
#while(Cnt < NrOfPlanes & !CloserPlane)
#local PlaneDist = PlaneDistances[Cnt];
#if (PlaneDist < PointDist)
#local vPlane = vnormalize(PlaneNormals[Cnt]);
#local DOT = vdot(p0, vPlane);
#if (DOT > 0)
#local CloserPlane = (PlaneDist + more < DOT);
#end // if
#end // if
#local Cnt = Cnt + 1;
#end // while
CloserPlane
#end // macro PlaneUnder
// Find all possible corners at the intersections of every triple
// of non-parallel planes and test each of them to see if they are
// "false" (i.e. with a plane "below"). Write all the real ones to
// a file. Write to another file which 3 planes each of the "real"
// corners are in the intersection of. Return the number of "real"
// corners found
#macro WriteCorners(PlaneNormals, PlaneDistances,
MapFileName, CornerFileName)
#local NrOfPlanes = dimension_size(PlaneNormals, 1);
#fopen MapFile MapFileName write
#fopen CornerFile CornerFileName write
#write (CornerFile, " \n")
#write (MapFile, " \n")
#local CornerCnt = 0;
#local PlaneCnt0 = 0;
#while (PlaneCnt0 < NrOfPlanes - 2)
#local vPl0 = PlaneNormals[PlaneCnt0];
#local PlaneCnt1 = PlaneCnt0 + 1;
#while (PlaneCnt1 < NrOfPlanes - 1)
#local vPl1 = PlaneNormals[PlaneCnt1];
#local PlaneCnt2 = PlaneCnt1 + 1;
#while (PlaneCnt2 < NrOfPlanes)
#local vPl2 = PlaneNormals[PlaneCnt2];
#if (S3Prod(vPl0, vPl1, vPl2) != 0)
#local pPl0 = PlaneDistances[PlaneCnt0]*vnormalize(vPl0);
#local pPl1 = PlaneDistances[PlaneCnt1]*vnormalize(vPl1);
#local pPl2 = PlaneDistances[PlaneCnt2]*vnormalize(vPl2);
#local pCommon = pl2pl2pl(pPl0, vPl0, pPl1, vPl1, pPl2, vPl2);
#if (!PlaneUnder(pCommon, PlaneNormals, PlaneDistances))
#write (CornerFile, pCommon, ",\n")
#write (MapFile, <PlaneCnt0, PlaneCnt1, PlaneCnt2>, ",\n")
#local CornerCnt = CornerCnt + 1;
#end // if
#end // if
#local PlaneCnt2 = PlaneCnt2 + 1;
#end // while
#local PlaneCnt1 = PlaneCnt1 + 1;
#end // while
#local PlaneCnt0 = PlaneCnt0 + 1;
#end // while
#fclose MapFile
#fclose CornerFile
CornerCnt
#end // macro WriteCorners
// Read numbers or vectors from a text file into an array
// Note: There's no check for nr of items in the file or the size of
// the array.
#macro ReadFileToArray(FileName, Array)
#local NrOfItems = dimension_size(Array, 1);
#fopen ReadFile FileName read
#local Cnt = 0;
#while (Cnt < NrOfItems)
#read (ReadFile, Temp)
#declare Array[Cnt] = Temp;
#local Cnt = Cnt + 1;
#end // while
#fclose ReadFile
#end // macro ReadFileToArray
// Output the components of a 3D vector to the debug window
#macro PrintVector(v0)
#debug "<"
#debug str(v0.x, 9, 6)
#debug ", "
#debug str(v0.y, 9, 6)
#debug ", "
#debug str(v0.z, 9, 6)
#debug ">"
#end // macro PrintVector
// Put spheres at every point in the array
#macro PlotCorners(CornerArray, Radius)
#local NrOfCorners = dimension_size(CornerArray, 1);
union {
#local Cnt = 0;
#while (Cnt < NrOfCorners)
sphere { CornerArray[Cnt], Radius }
#local Cnt = Cnt + 1;
#end // while
}
#end // macro PlotCorners
// Output the data for the planes given by the two arrays to the
// debug window
#macro ListPlanes(PlaneNormals, PlaneDistances)
#debug "\n"
#local NrOfPlanes = dimension_size(PlaneNormals, 1);
#local Cnt = 0;
#while (Cnt < NrOfPlanes)
#debug "\nPlane No. "
#debug str(Cnt, 3, 0)
#debug " Normal vector: "
PrintVector(PlaneNormals[Cnt])
#debug " Distance from origo: "
#debug str(PlaneDistances[Cnt], 0, -1)
#local Cnt = Cnt + 1;
#end // while
#debug "\n"
#end // macro ListPlanes
// Output the data for the corners given in the two arrays to the
// debug window
#macro ListCorners(CornerMapArray, CornerArray)
#debug "\n"
#local NrOfCorners = dimension_size(CornerMapArray, 1);
#local Cnt = 0;
#while (Cnt < NrOfCorners)
#local CI = CornerMapArray[Cnt];
#debug "\nCorner No. "
#debug str(Cnt, 4, 0)
#debug ": Plane "
#debug str(CI.x, 3, 0)
#debug " & Plane "
#debug str(CI.y, 3, 0)
#debug " & Plane "
#debug str(CI.z, 3, 0)
#debug " Common point: "
PrintVector(CornerArray[Cnt])
#local Cnt = Cnt + 1;
#end // while
#debug "\n"
#end // macro ListCorners
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Parameters for the bevelled box
#declare L = 3; // Length
#declare H = 1; // Height
#declare W = 2; // Width
#declare BevelSize = 0.1;
//#declare BevelSize = BevelSize/sqrt(2);
#declare SphereRadius = 0.03;
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Initialize arrays for the needed planes
#declare NrOfPlanes = 18;
#declare ArraysOfNormals =
array[NrOfPlanes]{
+x, +y, +z,
-x, -y, -z,
+x+y, +x+z, +y+z,
+x-y, +x-z, +y-z,
-x+y, -x+z, -y+z,
-x-y, -x-z, -y-z
}
#declare ArrayOfDistances = array[NrOfPlanes]
#declare Cnt = 0;
#while (Cnt < NrOfPlanes)
#declare vN = ArraysOfNormals[Cnt];
#declare ArrayOfDistances[Cnt] =
vdot(vnormalize(vN), vN*<L, H, W>)/2 - (Cnt < 6 ? 0 : BevelSize);
#declare Cnt = Cnt + 1;
#end // while
ListPlanes(ArraysOfNormals, ArrayOfDistances)
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Call the macros
#declare NrOfCorners = WriteCorners(
ArraysOfNormals,
ArrayOfDistances,
"PlaneTriples.txt",
"Corners.txt"
);
#declare ArrayMapOfCorners = array[NrOfCorners]
#declare ArrayOfCorners = array[NrOfCorners]
ReadFileToArray("PlaneTriples.txt", ArrayMapOfCorners)
ReadFileToArray("Corners.txt", ArrayOfCorners)
ListCorners(ArrayMapOfCorners, ArrayOfCorners)
object {
MakeConvex(ArraysOfNormals, ArrayOfDistances)
pigment { color Grey }
}
object {
PlotCorners(ArrayOfCorners, SphereRadius)
pigment { color Red }
}
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
background { color Blue/2 }
light_source { <4, 3, -5>*10 color 1.2*White }
camera {
location <2, 1, -2>*1.2
look_at <0, 0, 0>
}
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
Post a reply to this message
|
|