|
|
This is not a question but just the results of what I have been working on.
Below are 3 macros (and an example) of how to smoothly join a cylinder and a
sphere using nothing but CSG.
All you have to know is Pythagoras' Theorem (c^2 = a^2 + b^2) and the fact
that sin(angle) = opposite / hypotenuse.
The best part is that the angle in sin(angle) is irrelevant here.
This stuff was inspired by Tor Olav Kristenson's "CSG-Glass_Ball.jpg" from
his site.
I thought it looked awesome and I wanted to know how to do it.
This is what I have come up with and I am currently working on joining two
cylinders together at right angles to each other like the handle of a
coffee cup.
The only way I can think of to do it is to bend a torus in a circular arc
and cut that out of a slightly larger cylinder. The reason the torus needs
to be bent is to keep in line with the curvature of the large cylinder.
The only way I can think of to do this is an isosurface and I did in fact do
it but it didn't fit perfectly like the cylinder/sphere join. Oh well...
I hope this inspires others to do smooth CSG!!!
Nathan
// Returns a csg connector that connects a cylinder to the outside of a
larger sphere
// r - radius of sphere
// a - radius of cylinder
// d - distance of cylinder's cap from the centre of the sphere
// Notes:
// * the returned object is pointing directly up (in the +y direction)
// * the following rules must be observed: r>a>0 and d<r (I don't know if
d>a or something)
#macro Cyl_Sphere_Connector(r,a,d)
#local p=0.5*(d*d+a*a-r*r)/(r-a);
intersection
{
cylinder{0 d*y r*(a+p)/(r+p)}
torus{p+a p translate d*y inverse}
}
#end
// Returns an object to cut out of a sphere for a smooth inside join with a
smaller cylinder
// This macro is meant to be used in tandem with the
Cyl_SphereInside_Addon() macro
// r - radius of sphere
// a - radius of cylinder
// d - distance of cylinder's cap from the centre of the sphere
// Notes:
// * the returned object is pointing directly up (in the +y direction)
// * the following rules must be observed: r>a>0 and d<r (I don't know if
d>a or something)
#macro Cyl_SphereInside_Cutout(r,a,d)
#local p=-0.5*(d*d+a*a-r*r)/(r+a);
cylinder{2*r*y d*y r*(a+p)/(r-p)}
#end
// Returns an object to add on to a sphere for a smooth inside join with a
smaller cylinder
// This macro is meant to be used in tandem with the
Cyl_SphereInside_Cutout() macro
// You should first cut out the Cyl_SphereInside_Cutout() object and then
add this one on
// r - radius of sphere
// a - radius of cylinder
// d - distance of cylinder's cap from the centre of the sphere
// Notes:
// * the returned object is pointing directly up (in the +y direction)
// * the following rules must be observed: r>a>0 and d<r (I don't know if
d>a or something)
#macro Cyl_SphereInside_Addon(r,a,d)
#local p=-0.5*(d*d+a*a-r*r)/(r+a);
torus{p+a p translate d*y}
#end
// ******************************************* EXAMPLES
union
{
sphere{0 1}
object{Cyl_Sphere_Connector(1,0.2,2)}
object{Cyl_Sphere_Connector(1,0.2,2) rotate<0,0,-90>}
translate 2*x
texture{pigment{rgb<1,0,0.3>}finish{specular 0.3 roughness 0.1 reflection
0.3}}
}
union
{
difference
{
sphere{0 1}
object{Cyl_SphereInside_Cutout(1,0.2,0.5)}
object{Cyl_SphereInside_Cutout(1,0.2,0.5) rotate<-90,0,0>}
}
object{Cyl_SphereInside_Addon(1,0.2,0.5)}
object{Cyl_SphereInside_Addon(1,0.2,0.5) rotate<-90,0,0>}
translate -2*x
texture{pigment{rgb<0,0.3,1>}finish{specular 0.3 roughness 0.1 reflection
0.3}}
}
camera
{
location<0,4,-5>
look_at<0,0,0>
right (image_width/image_height)*x
}
light_source{<15,25,-25>rgb 1.2}
plane{y,-2 pigment{rgb 1}}
// END OF CODE
Post a reply to this message
|
|
|
|
> This is what I have come up with and I am currently working on joining two
> cylinders together at right angles to each other like the handle of a
> coffee cup.
> The only way I can think of to do it is to bend a torus in a circular arc
> and cut that out of a slightly larger cylinder. The reason the torus needs
> to be bent is to keep in line with the curvature of the large cylinder.
> The only way I can think of to do this is an isosurface and I did in fact do
> it but it didn't fit perfectly like the cylinder/sphere join. Oh well...
This is a tricky problem in CSG - I've tried to do something similar in the
past without resorting to an isosurface and the results weren't too great.
The surface required to join the two cylinders was beyond my somewhat
limited CSG abilities. I tried using a sphere_sweep to make a 'bent torus'
from which to cut, but the precision required by the spline to get a smooth
join was, I thought, insurmountable.
L
-
Post a reply to this message
|
|
|
|
"Loki" <nomail@nomail> wrote:
> This is a tricky problem in CSG - I've tried to do something similar in the
> past without resorting to an isosurface and the results weren't too great.
> The surface required to join the two cylinders was beyond my somewhat
> limited CSG abilities. I tried using a sphere_sweep to make a 'bent torus'
> from which to cut, but the precision required by the spline to get a smooth
> join was, I thought, insurmountable.
>
> L
> -
Insurmoutable is about right...unfortunately.
However, after much trial and alot of error, the following variable
substitution will bend (almost) any object in a circular arc around the z
axis:
Let f(x,y,z) be the function you wish to bend.
i.e. f(x,y,z)=f_torus(y,x,z,0.8,0.2) -- a torus in the y-z plane (notice
that it's not in the x-y plane like normal)
The substitution is as follows:
bent_f(x,y,z)=f(sqrt(x*x+y*y)-r,atan2(y,x),z)
"r" is what I call the "radius of curvature" which I shall now explain:
The torus that I provided above is exactly 2 units long in the y-axis. The
bent_f mapping is periodic with a period of (of course) 2*pi.
This means that an object (such as a torus) longer than 2*pi units in length
will map more than once around a circle.
There is no way to stop this, save from scaling the torus. However this
action results in a bent circular path around the torus (just like scaling
any normal torus by more than a factor 1 in any axis). This is something I
wish to avoid.
The "r" variable specifies the radius of the circular arc you are going to
map your function to.
Basically the bent_f substitution bends an object like a torus around a
cylinder of radius r that is travelling down the z axis.
The amount of the circular arc on the cylinder that is taken up by the
mapping is determined completely by the length of the original function in
the y-axis.
Thus if a torus is pi/2 units long (in diameter) then it will occupy an arc
length of (pi/2)/(2*pi) = 1/4 of the entire arc length.
Changing the "r" variable will not change how much of the cylinder is
covered; it will only change how "big" the resulting object will be.
In conclusion this bent torus can be used to cut away a slightly larger
cylinder to give a smooth trnsition between a large cylinder and a
(smaller) one at right angles to the cylinder.
Nathan
Post a reply to this message
|
|