Archived

This topic is now archived and is closed to further replies.

Metaballs - Normals

This topic is 5764 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

That would probably work.

The problem comes when you introduce anti-metaballs that subtract energy. But my guess is that there would be a whole lot other issues to solve as well if such where to be added.

The extra step I referred to was not that you pre-divided the normal magnitude. It was that you used a higher power than I did, which looks better. I''m now trying to figure out the exact power to use when computing the normals.

- WitchLord

Share on other sites
To calc the energy from 1 ball I use: (And add forces for more balls)
rr = (x-tx1)*(x-tx1) + (y-ty1)*(y-ty1) + (z-tz1)*(z-tz1);Force = MB_SIZE*MB_SIZE/rr;

To calc the normal I use: (Add normals for more balls)
n = MB_SIZE*MB_SIZE / (sqrt(rr) * rr);pVertex->nx = (x-ballx)*n;pVertex->ny = (y-bally)*n;pVertex->nz = (z-ballz)*n;

Hope I''ve got it correct, and hope it helps,
Bas.

(ps: Can''t run your demo! Get an error about "DDRAW.DLL: DirectDrawCreateEx". I have no 3D card. Do I need to upgrade my DirectX 6.1 version first?)

Share on other sites
I''ve been tweaking my program a little, here''s a new screenshot:

I have changed the normal computation for my program so that it is now done like this:

inline D3DVECTOR CMetaBallApp::Normal(D3DVECTOR &Pos){  D3DVECTOR N = D3DVECTOR(0,0,0);  for( int i = 0; i < m_nNumBalls; i ++ )  {    D3DVECTOR v = Pos - m_Balls;    float m = SquareMagnitude(v);    m = SQRADIUS / (m*m);    N += v*m;  }  return Normalize(N);}

I couldn''t see much difference between using

m = SQRADIUS / (m*m);

and

m = SQRADIUS / (sqrt(m)*m);

so I decided to use the one that was faster. Though no performance difference was visible.

I''ll be uploading the new program to my site later today.

- WitchLord

Share on other sites
You''re almost making the same mistake I made (page 2, post 3), but I must say: Looks great! Can''t see the difference!

But after lozing the sqrt from this part you probably have to normalize, and the sqrt is back.

I think the sqrt() is there to make the vector (CenterBall to CurrentVertex) of unit length 1.
What do you get if you use the sqrt() and drop normalization?

Your metaballs look great, all 5! of them.

Share on other sites
If you want Phong mapping:
- Use a phong map (texture)
- Do environment mapping (use the x & y part of the vertex normals as texture coords)

Here's a PhongMap/Texture:

You can also add a picture-texture by:
- Use the PhongMap as a lightmap orso??? I have never done this with OpenGL or Direct3D, is this possible?
- Mixing it with the phong map. (But then you will not be able to rotate around it) (this would increase the speed of my software engine greatly, but the total engine isn't based on this, and after optimizing this will not support other models...but good idea for you!)

The disadvantage you have with phongmapping is: Your light must come out of the camera, in the Z direction.
Well, you don't have to, but then there's also a light spot on the other side (real ugly).

(ps: We're now in the 25 hottest topics of all time)

Edited by - baskuenen on May 26, 2000 12:35:17 AM

Share on other sites
You're right, I did some refurnishing in my functions and now everything looks much logical. Here's what they look like:

inline float CMetaBallApp::Energy(D3DVECTOR &Pos){  float e = 0;  for( int i = 0; i < m_nNumBalls; i++ )  {    float SqDistance = SquareMagnitude(Pos - m_Balls[ i ]);    e += SQRADIUS / SqDistance;  }  return e;}inline D3DVECTOR CMetaBallApp::Normal(D3DVECTOR &Pos){  D3DVECTOR N = D3DVECTOR(0,0,0);  for( int i = 0; i < m_nNumBalls; i ++ )  {    D3DVECTOR v = Pos - m_Balls[ i ];    float SqDistance = SquareMagnitude(v);    v /= (float)sqrt(SqDistance); // Normalize the vector    // We should scale this vector so that the contribution from this     // metaball is inversely proportional to the square distance, because    // the energy from it is also inversely proportional to the square     // distance.    N += (SQRADIUS / SqDistance)*v;  }  return Normalize(N);}

Can you see the similarities?

And I tried to drop the normalization of the normal after the summation but that doesn't work, the lighting gets all screwed. It's actually quite easy to see that it must be normalized. Think about what happens when you have two balls and you take a point exactly between them, then the normal will have zero length. If you move just a little bit away from this spot the normal will be small but it can be normalized to give a unitlength direction.

During this testing I also tested to change the energy function so that it has linear falloff. It still produces metaballs, but they have slightly different properties; They grow a lot more when they are close to each other.

nVidia has some cool demos and papers on how to go about to create phong mapping with specular highlights with OGL and D3D. I had initially planned to implement that and cub environmentmapping on my metaballs, but now I think that I should go back to writing my game instead. Maybe I'll dig up my metaballs again later and add some cool effects to them.

It's been fun.

- WitchLord

Edited by - WitchLord on May 27, 2000 1:50:04 AM

Share on other sites
n = MB_SIZE*MB_SIZE / (sqrt(rr) * rr);
--
This:
n = MB_SIZE*MB_SIZE / (sqrt(rr) * rr);

Should be:
n = MB_SIZE*MB_SIZE / (rr * rr);

If you're using "force+=radius/distance;" (not square distance), then the "n = MB_SIZE / (sqrt(rr) * rr);" is correct.

I still don't get why you have MB_SIZE*MB_SIZE and not only MB_SIZE...

Howeved I downloaded your metaballs demo and it looks good!

-Hans

Edited by - Hans on May 27, 2000 3:07:51 AM

Share on other sites
Even though I haven''t had the energy to sit down and prove my theory with maths, I believe you are wrong, Hans. Both the normal and force computations should be the same:

P: Point to be computed
C: Center of metaball
v = P - C;
r = Magnitude(v);
force += n;
normal += n*v/r;

or

v = P - C;
rr = SquareMagnitude(v);
force += n;
normal += n*v/sqrt(rr);

---

baskuenen, when I tried your program it desided to use 16 bit mode because my GeForce 256 don''t support 24 bit mode. Perhaps you should implement you engine to support 32 bit also.

- WitchLord

Share on other sites
I''ve now tried it without the sqrt(), and it looks a bit sharper. Also it''s faster (not noticeable though).

The phong spot looks a bit better this way, but the sharp edges between the balls are a bit too sharp.

Here''s a new screenshot:

The use of sqrt() or not is getting a bit confusing to me. I can understand the math using sqrt(), but it makes no sense to me if I lose the sqrt().

Hans: why lose the sqrt? It''s used to make the normal in the calculation of unit length 1, before dividing it with the force from that single ball. (But in practice it almost seems right to lose the sqrt!)

Good idea, the 32bit color depth support...will do that.

Share on other sites
What would be a good idea for implementing metaballs into a game? Another remake of tetris, but this time with blobby objects, seems a little boring!

It could be a nice way to have an animated man running around. Although texturing this would be quite hard.

Maybe this question is a little of the topic: Imagine a running man; How do I calculate the anim paths for this? (the metaball coords in this case). Can a few simple sin & cos be enough, or is human movement more complex?
I can imagine setting up a tree...

Edited by - baskuenen on May 27, 2000 4:12:37 PM

• 17
• 19
• 23
• 10
• 21