Imagyx
|
|
« on: September 21, 2011, 06:49:35 PM » |
|
Hi. I'm new here and hope to get a little help. I wrote myself a program to calculate the classic 2D-Mandelbrot years ago and it's gotten bigger and bigger. But I want to try something new and write a program for the 3D-Mandelbulb. I found this forum and hope to find some simple tutorial first, can you help me with that ? Actually I want to write that one in Java, as well as the 2D-program before, which is easy to use and enables me to use full power of all 4 cores. (I don't know how to work with the GPU, I want to try it this way) Greetz@ all people having fun here with fractals & Co.
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
|
Imagyx
|
|
« Reply #2 on: September 22, 2011, 12:17:27 AM » |
|
Thank you a lot, that is exactly what I was hoping to find, but couldn't. I read through all five parts once and I will reread it again tomorrow. The description seems to be able to lead me to a first simple implementation..(and maybe more) Great work !! When I'm done with that program or any problems appear I will post here again.
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Imagyx
|
|
« Reply #3 on: September 22, 2011, 05:35:55 PM » |
|
I tried to use some of the stuff mentioned in the tutorial, but it doesn't start from scratch, so I have some problems here: Let me post the actual code first, maybe you can help me with that. I think I don't actually understand where to start. public void recalculate() { /*||Created on 05.05.2010 18:28:16||*/ offscreen = new BufferedImage(Draw3D.sizeX,Draw3D.sizeY,BufferedImage.TYPE_INT_RGB); Graphics2D g = offscreen.createGraphics(); Graphics2D g2 = (Graphics2D) getGraphics(); double p = 8.0;//z^8+c double bailout = 2.0; double threshold = Math.pow(10.0,-4); int maxIter = 100; double diffX = 3.0/sizeX; double diffY = 3.0/sizeY; for (int ix = 0; ix < sizeX; ix++) { double x = -1.5+ix*diffX; for (int iy = 0; iy < sizeY; iy++) { double y = -1.5+iy*diffY; V3D w = new V3D(0,0,0); V3D c = new V3D(x,y,0); double iter = trace(w,c,10,threshold,bailout,maxIter,p); if(iter > 1){ System.out.println(""+iter); } Color col = getColorFromCNT((int) iter,0,1); g.setColor(col); g.drawLine(ix,iy,ix,iy); g2.setColor(col); g2.drawLine(ix,iy,ix,iy); } } repaint(); }
public double trace(V3D origin, V3D destination, int maxRaySteps, double minDist, double bailout, int maxIter,double p) { double totalDistance = 0.0; int step; for(step=0; step < maxRaySteps; step++){ V3D z = origin.add(destination.skalarMult(totalDistance)); double distance = DistanceEstimator(z,0.5,bailout,maxIter,p); totalDistance += distance; if (distance < minDist){ break; } } return 1.0-(double)step/(double)maxRaySteps; } private double DistanceEstimator(V3D z, double factor,double bailout, int maxIter, double p) { /*||Created on 22.09.2011 16:19:27||*/ double dr = 1.0; double r = 0; int iter = 0; while(iter < maxIter && r < bailout){ r = z.abs(); double theta = Math.atan2(z.abs2D_12(),z.getZ()); double phi = Math.atan2(z.getY(), z.getX()); dr = Math.pow(r,p-1.0) * p * dr + 1.0; theta *= p; phi *= p; double sint = Math.sin(theta); double cost = Math.cos(theta); double sinp = Math.sin(phi); double cosp = Math.cos(phi); z.set(sint*cosp,sint*sinp,cost); z = z.skalarMult(Math.pow(r,p)); iter++; } return factor*Math.log(r)*r/dr; }
I think the main problem is the definition of V3D w = new V3D(0,0,0); V3D c = new V3D(x,y,0);
What is a first correct viewpoint ? E.g. when I want to iterate through the normal 2D-Mandelbrot I start with c between [-3,3]x[-3,3] and get the picture in the middle of my screen. So that's what I mean with a good starting viewpoint. w is the actual z I'm iterating, but I chose w here because x,y,z are already the coordinates of w and I want to avoid something like z.x,z.y,z.z Please help me
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Syntopia
|
|
« Reply #4 on: September 22, 2011, 06:01:17 PM » |
|
The Mandelbulb is located at the origin of the coordinate system, and has approximately unit radius. For testing you could use this DE: float DE(vec3 pos) { return length(pos)-1.0; }
If you can see a sphere, you should be able to see the Mandelbulb at the same location.
For the camera rays, you probably want some kind of perspective projection, but you could start out by mapping the viewport corners from (-2,-2,-2) to (2,2,-2) as start positions, and then ray march at a direction along the positive z-axis.
|
|
|
Logged
|
|
|
|
Imagyx
|
|
« Reply #5 on: September 22, 2011, 11:37:51 PM » |
|
I did it !!! First the sphere.... ...and now the mandelbulb: (I used a colorset from my 2D-program, nice to know I can use all the colorsets from earlier for 3D as well ) So thank you very much for your fast help, I think I might be able to do some experiments now.
|
|
« Last Edit: September 22, 2011, 11:40:17 PM by Imagyx »
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
cKleinhuis
|
|
« Reply #6 on: September 23, 2011, 01:18:56 AM » |
|
|
|
|
Logged
|
---
divide and conquer - iterate and rule - chaos is No random!
|
|
|
Imagyx
|
|
« Reply #7 on: September 23, 2011, 03:13:28 PM » |
|
Hello and thank you I have another question now I managed to get another viewpoint with exchanging axes. I don't have the rays going in a positive z-direction but also the possibility now to go in positive x- or y-direction which gives a new view of the mandelbulb. But how can I rotate freely ?
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Syntopia
|
|
« Reply #8 on: September 23, 2011, 03:35:56 PM » |
|
Hi, nice to see you got it working!
One way to rotate the Mandelbulb is to simply multiply the argument to the DE-function by a 3D rotation matrix (for instance expressed using Euler angles).
But at some point you will need some proper perspective projection. Try searching for 'pinhole camera model' - there must be some tutorials out there.
|
|
|
Logged
|
|
|
|
Imagyx
|
|
« Reply #9 on: September 23, 2011, 05:09:34 PM » |
|
Yeah, thanks to your advice and nice tutorials it's finally there The idea with a rotation matrix is a good one, only I didn't know where to apply it I'm trying step by step, so the rotation first, "pinhole camera" later... let's see where this goes.
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Imagyx
|
|
« Reply #10 on: September 23, 2011, 08:48:12 PM » |
|
I have a first zoom in that is now possible. Looks really nice I think. But I still have some problems with rotating, I need more time to understand completely what I actually do there Another important question is, how can I get more detail when zooming in. I tried to change different parameters, but I think a parameter-stepping is necessary, am I right there ? So depending on how far I move towards the fractal I need to adjust some of the parameters ? Which would that be? The number of raySteps, the minDistance, the number of iterations in rayStepping ? I tried all of them alone and together, but it got worse. Also the colorchoice doesn't only depend on the number of raySteps alone, right ? Enough so far, more the next days
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Imagyx
|
|
« Reply #11 on: September 26, 2011, 03:36:01 PM » |
|
I think I understand the effect of the different parameters a little better now. I post a new rendered picture below which took ~ 200 sec. to render with a resolution of 3000x3000. But I still need to figure out how to rotate freely in my application, so this one is only some positive x-zoom again with different colors, zoomed more deeply. (If you ever wonder, what is he saying I'm not a native english speaker, so correct me if there's something wrong, please, I take no offense )
|
|
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Syntopia
|
|
« Reply #12 on: September 26, 2011, 10:30:31 PM » |
|
Your english in fine - at least to me, but I'm not native english speaking either :-) Did you try the rotation matrix thing, something like: Matrix3x3 rotationMatrix = Matrix3x3::fromEulerAngles(...);
float DE(vec3 pos) { pos = rotationMatrix*pos; ... the usual code ... }
|
|
|
Logged
|
|
|
|
Imagyx
|
|
« Reply #13 on: September 27, 2011, 03:23:31 PM » |
|
That is exactly what I did. I calculated my rotation matrix as mentioned in http://upload.wikimedia.org/math/d/7/d/d7d24840d643af424de6a73730aea6d9.pngon http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29for three angles (each for one axis). It works for one axis, but with the other two angles the mandebulb vanishes from my screen. I think I may know my problem: V3D z = new V3D(origin.xyz); z = Draw3D.rotationMatrix.mult(z); double distance = 0; for(step=0; step < maxRays && z.getZ() < 4.0; step++){ distance = formeln[Draw3D.formel].DistanceEstimator(z,refine,bailout,maxIter,p); totalDistance += distance; if (distance < minDist || distance > 100){ break; }else{ z.xyz[2] += distance; <------------------------------------------------------------ this is incorrect, right ? } }
Without rotating the raymarching goes along the z-axis, but with rotation I have to change something here, right ? only changes the z-coordinate of the actual vector
|
|
« Last Edit: September 27, 2011, 03:25:34 PM by Imagyx »
|
Logged
|
During difficult times, keep steady and play the match.
|
|
|
Syntopia
|
|
« Reply #14 on: September 27, 2011, 08:53:39 PM » |
|
That is exactly what I did.
Well, it is not what your code says :-) The idea is to rotate the fractal, and keep the camera fixed. You can do this by applying the rotation inside the DE-function, i.e: put 'z = Draw3D.rotationMatrix.mult(z);' inside the 'DistanceEstimator(...);' function.
|
|
|
Logged
|
|
|
|
|