Welcome to Fractal Forums

Fractal Software => Programming => Topic started by: tryptophan on May 01, 2013, 10:44:52 PM




Title: Beveled cube distance function
Post by: tryptophan on May 01, 2013, 10:44:52 PM
Hi I've made a beveled cube by doing an intersection on all of the edges of a cube with a bunch of planes. I have a couple of technical difficulties and am also wondering if this the most efficient way to go about doing this. Basically I've taken the cube and intersected it 12 times with 12 different planes to cut off the 12 edges. I think I could do the same thing by intersecting the cube with 3 rotated cubes but I'm not sure if that would be more efficient if I needed to use a rotation matrix to rotate the cubes.
Code:
float bevCube (vec3 p, vec3 s, float b)
{


float cCut= b + length(vec3(1.0,1.0,1.0)*b) - length(vec3(1.0,1.0,0.0)*b);


float box = sdBox(p,s);

//Top edges
float cut1 = sdPlane(p,normalize(vec4(0.0,1.0,1.0,-b)));
float cut2 = sdPlane(p,normalize(vec4(0.0,1.0,-1.0,-b)));
float cut3 = sdPlane(p,normalize(vec4(1.0,1.0,0.0,-b)));
float cut4 = sdPlane(p,normalize(vec4(-1.0,1.0,0.0,-b)));
float m1 = max(max(max(cut1,cut2),cut3),cut4);

//bottom edges
float cut5 = sdPlane(p,normalize(vec4(0.0,-1.0,1.0,-b)));
float cut6 = sdPlane(p,normalize(vec4(0.0,-1.0,-1.0,-b)));
float cut7 = sdPlane(p,normalize(vec4(1.0,-1.0,0.0,-b)));
float cut8 = sdPlane(p,normalize(vec4(-1.0,-1.0,0.0,-b)));
float m2 = max(max(max(cut5,cut6),cut7),cut8);

//vertical edges
float cut9 = sdPlane(p,normalize(vec4(1.0,0.0,1.0,-b)));
float cut10 = sdPlane(p,normalize(vec4(-1.0,0.0,1.0,-b)));
float cut11 = sdPlane(p,normalize(vec4(1.0,0.0,-1.0,-b)));
float cut12 = sdPlane(p,normalize(vec4(-1.0,0.0,-1.0,-b)));
float m3 = max(max(max(cut9,cut10),cut11),cut12);

//top corners
float cut13 = sdPlane(p,normalize(vec4(1.0,1.0,1.0,-cCut)));
float cut14 = sdPlane(p,normalize(vec4(-1.0,1.0,1.0,-cCut)));
float cut15 = sdPlane(p,normalize(vec4(1.0,1.0,-1.0,-cCut)));
float cut16 = sdPlane(p,normalize(vec4(-1.0,1.0,-1.0,-cCut)));
float m4 = max(max(max(cut13,cut14),cut15),cut16);

//bottom corners
float cut17 = sdPlane(p,normalize(vec4(1.0,-1.0,1.0,-cCut)));
float cut18 = sdPlane(p,normalize(vec4(-1.0,-1.0,1.0,-cCut)));
float cut19 = sdPlane(p,normalize(vec4(1.0,-1.0,-1.0,-cCut)));
float cut20 = sdPlane(p,normalize(vec4(-1.0,-1.0,-1.0,-cCut)));
float m5 = max(max(max(cut17,cut18),cut19),cut20);

return max(max(max(max(max(box,m1),m2),m3),m4),m5);
So my first question is this - is this the best way to go about doing this? I would like to use this a building block for a fractal so it be nice if it was the least amount of processing possible

If so I'm having one problem with this method. In order to bevel the corners after the edges have been beveled I've used another 8 planes to cut these corners. I can't seem to figure out the proper distance to cut this corner in relation to the cut edges. I've tried to take the length of the distance to the corner - length to the edge and adding that to distance of the bevel but it isn't right. Would anyone have any insight on how to do this calculation?

Below are two images. One of what it should look like at all bevel scales and another at using the cCut line of code above.
thanks
Keith


Title: Re: Beveled cube distance function
Post by: glennmarshall on May 08, 2013, 06:57:09 PM
I was thinking the rounded box formula here would be a starting point
http://iquilezles.org/www/articles/distfunctions/distfunctions.htm

if you could some how make the rounding factor a flat linear value - it might work, the math is beyond me sadly..


Title: Re: Beveled cube distance function
Post by: Syntopia on May 08, 2013, 08:33:58 PM
Try taking advantages of the symmetries of the cube, using the abs operator (which is computationally free on a GPU). This way you only have to take care of three edges and one corner:

Code:
#include "DE-Raytracer.frag"

uniform float Edge; slider[1,1.8,2]
uniform float Corner; slider[1,2.4,3]

float  DE(vec3 z) {
z = abs(z);
        float d = max(max(z.x+z.y-Edge, z.x+z.z-Edge),z.z+z.y-Edge)/sqrt(2.0);  // edges
d = max(d, max(max(z.x-1., z.y-1.),z.z-1.)); // box
d = max(d, (z.x+z.y+z.z-Corner)/sqrt(3.0)); // corner
return d;
}

Image:
(http://blog.hvidtfeldts.net/media/cube.jpg)



Title: Re: Beveled cube distance function
Post by: tryptophan on May 08, 2013, 09:06:55 PM
Thanks for the tips guys. Yeah Glen I knew about the round cube but at the time I didn't think that method could be used. I'm not a math expert either so it wasn't immediately clear.

Syntopia thank you for the formula. It looks like a much more efficient method. I understand most of it but I have one question.  Why do you need to divide by the square and cube roots? I can see that is a square root for edges because they a 2d cut and the corner is a cubed root because it is a 3d cut. Is it to normalize the function?



Title: Re: Beveled cube distance function
Post by: Syntopia on May 08, 2013, 09:34:08 PM
Thanks for the tips guys. Yeah Glen I knew about the round cube but at the time I didn't think that method could be used. I'm not a math expert either so it wasn't immediately clear.

Syntopia thank you for the formula. It looks like a much more efficient method. I understand most of it but I have one question.  Why do you need to divide by the square and cube roots? I can see that is a square root for edges because they a 2d cut and the corner is a cubed root because it is a 3d cut. Is it to normalize the function?

For the edges you need to calculate the distance from a plane with the given normal, i.e.
dot(z, normalize(vec3(1,1,0)))
which can be written as
(z.x+z.y)/sqrt(2.0)

The same with the corner, you need to divide by length(vec3(1,1,1)).

If you don't do this your DE will overstep, and you will get artifacts (I first forgot to normalize myself).


Title: Re: Beveled cube distance function
Post by: tryptophan on May 09, 2013, 12:02:16 PM
Thanks again. The explanation is really helpful. I've started hacking together my own DE raymarcher basically by looking at your raytracer and some Inigo Quilez info/work. I think I'm starting to actually get a handle of what's going on. Still have tons to learn.   

thanks
Keith


Title: Re: Beveled cube distance function
Post by: cKleinhuis on May 09, 2013, 12:10:56 PM
and me hopes you will produce a nice competition entry :D


Title: Re: Beveled cube distance function
Post by: tryptophan on May 09, 2013, 08:32:38 PM
Quote
and me hopes you will produce a nice competition entry

Thanks Christian! I'm thinking about the latest render but I'm not sure it doesn't have much audio syncing. https://vimeo.com/65596042

I won't be doing another song until after May 20th but I might be able to pull something off on the following week.