Texturing Xen's built-in Sphere

Oct 2, 2010 at 7:26 AM
Edited Oct 2, 2010 at 7:27 AM

I'm probably doing something strange, but I cannot figure out why my texture has a 'seam'... 

Screenshot here : http://www.fallingdownstairs.net/images/sphere-issue.png

I'm setting it up like this:

 

            _geometry = new Sphere(Vector3.One * 100, 128, false, false, true);
            _transform = Matrix.CreateRotationX(MathHelper.ToRadians(90));

            MaterialShader material = new MaterialShader();
            Vector3 lightDirection = new Vector3(0.5f, 0, 0.5f);

            material.TextureMap = textureMap;
            material.Lights = new MaterialLightCollection();
            material.UsePerPixelSpecular = true;
            material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f;	
            material.Lights.AddDirectionalLight(true, lightDirection, Color.Gray);			
            material.SpecularColour = Color.LightYellow.ToVector3();

            _shader = material;

 

Rendering like this:

 

        public void Draw(DrawState state)
        {
            state.PushWorldMatrixMultiply(ref _transform);

            _shader.Bind(state);
            _geometry.Draw(state);

            state.PopWorldMatrix();
        }

 

Coordinator
Oct 2, 2010 at 7:31 AM

As a guess, it's probably set to Clamp in the shader?

Oct 2, 2010 at 7:47 AM

On further investigation, this is the issue

Screenshot: http://www.fallingdownstairs.net/images/sphere-issue.png

Looks like the UV is correct, but the vertices where they meet, goes back to 0 -> 1 due to them being side by side... Any idea how to get around this?

Coordinator
Oct 2, 2010 at 4:50 PM

Ok, you are right.

The geometry doesn't duplicate the vertices along the seam.

In order for it to do that, I think these are the changes that are required (forgive me if they are wrong, I've got a cold right now)

In Sphere.cs,
change:
for (int x = 0; x < div; x++)
to:
for (int x = 0; x < div + 1; x++)

And change:
startIndex += div;
To:
startIndex += div + 1;

.. 'div' is the number of divisions along the current ring of the sphere being generated. So basically, the first change makes it generate a new vertex in each ring, the second change makes sure the indices are incremented correctly.

Oct 2, 2010 at 7:29 PM

Unfortunately, that yields the same issue...  Although, I'm not exactly sure why, from the look of things while debugging, it looks like it should work fine...

Here are the vertices of the first ring created

[2]: {Position:{X:10.51042 Y:0 Z:100} Normal:{X:0.1045285 Y:0 Z:0.9945219} TextureCoordinate:{X:0 Y:0.03333334}}
[3]: {Position:{X:6.553142 Y:8.217381 Z:100} Normal:{X:0.06517243 Y:0.08172365 Z:0.9945219} TextureCoordinate:{X:0.1428571 Y:0.03333334}}    
[4]: {Position:{X:-2.338789 Y:10.24691 Z:100} Normal:{X:-0.02325977 Y:0.1019077 Z:0.9945219} TextureCoordinate:{X:0.2857143 Y:0.03333334}}   
[5]: {Position:{X:-9.469564 Y:4.5603 Z:100} Normal:{X:-0.0941769 Y:0.04535319 Z:0.9945219} TextureCoordinate:{X:0.4285714 Y:0.03333334}}   
[6]: {Position:{X:-9.469564 Y:-4.560302 Z:100} Normal:{X:-0.09417689 Y:-0.0453532 Z:0.9945219} TextureCoordinate:{X:0.5714285 Y:0.03333334}} 
[7]: {Position:{X:-2.33879 Y:-10.24691 Z:100} Normal:{X:-0.02325978 Y:-0.1019077 Z:0.9945219} TextureCoordinate:{X:0.7142857 Y:0.03333334}}    
[8]: {Position:{X:6.553144 Y:-8.217379 Z:100} Normal:{X:0.06517246 Y:-0.08172363 Z:0.9945219} TextureCoordinate:{X:0.8571429 Y:0.03333334}}    
[9]: {Position:{X:10.51042 Y:1.837701E-06 Z:100} Normal:{X:0.1045285 Y:1.827634E-08 Z:0.9945219} TextureCoordinate:{X:1 Y:0.03333334}}

 

From the look of it, the tex coord goes from 0 to 1 like it should...

Perhaps the indices are still incorrect?

Coordinator
Oct 2, 2010 at 8:14 PM

Yeah, they will be.

There is some very sneaky logic in the index setup, due to how each ring of the sphere contains a different number of vertices. All the indices are modulo with the divider value, so they will be wrong.

Your other option, is revert those changes, and change:
float ax = x / (float)div * (float)Math.PI * 2.0f;
to:
float ax = x / (float)Math.Max(1, div - 1) * (float)Math.PI * 2.0f;

It means there will some degenerate triangles, but whatever. :-)

Oct 2, 2010 at 11:13 PM

That seemed to do the trick, thanks!