生成顶点球点球

2023-09-08 00:25:20 作者:你若不离不弃我便身死相随

在的DirectX移动照明样品,一个圆筒以下面的方式产生的:

In the DirectX mobile lighting sample, a cylinder is generated in the following manner:

for( DWORD i=0; i<50; i++ )
            {
                FLOAT theta = (2*D3DMX_PI*i)/(50-1);
                pVertices[2*i+0].position = D3DMXVECTOR3( (float)sin(theta),-1.0f, (float)cos(theta) );
                pVertices[2*i+0].normal   = D3DMXVECTOR3( (float)sin(theta), 0.0f, (float)cos(theta) );
                pVertices[2*i+1].position = D3DMXVECTOR3( (float)sin(theta), 1.0f, (float)cos(theta) );
                pVertices[2*i+1].normal   = D3DMXVECTOR3( (float)sin(theta), 0.0f, (float)cos(theta) );
            }

是否有一个类似的方法来生成顶点DirectX中移动的球体(如三角形带或其他方式)? (AFAIK有没有D3DMXCreateSphere法)

Is there a similar way to generate vertices for a sphere in DirectX Mobile(as a triangle strip or otherwise)? (AFAIK there's no D3DMXCreateSphere method)

最终的解决方案.Thanks到quarternion所有他的帮助。

The final solution .Thanks to quarternion for all his help.

void CreateSphere()
{
    const int iFactor = 20;
    int iPos = 0;

    arr_Vertices = new CUSTOMVERTEX[ui_VCount];
    ui_ShapeCount = iFactor *iFactor * 2; // use when rendering

    float arrV[iFactor* iFactor][3];

    for (DWORD j= 0; j < iFactor; j ++)
    {
        FLOAT theta = (D3DMX_PI*j)/(iFactor);

        for( DWORD i=0; i<iFactor; i++ )
        {
            iPos = j*iFactor+i;
            FLOAT phi = (2*D3DMX_PI*i)/(iFactor);
            arrV[iPos][0] = (float)(sin(theta)*cos(phi));
            arrV[iPos][1] = (float)(sin(theta)*sin(phi));
            arrV[iPos][2] = (float)(cos(theta));

            /*std::cout << "[" << j <<"][" << i << "] = " << arrV[iPos][0]  
                << "," << arrV[iPos][1] << "," << arrV[iPos][2] <<std::endl;*/
        }
    }

    int iNext = 0;

    for (DWORD j= 0; j < iFactor; j ++)
    { 

        for( DWORD i=0; i<iFactor; i++ )
        {
            if (i == iFactor - 1)
                iNext = 0;
            else iNext = i +1;

            iPos = (j*iFactor*6)+(i*6);
            arr_Vertices[iPos].position = D3DMXVECTOR3( arrV[j*iFactor+i][0], arrV[j*iFactor+i][1], arrV[j*iFactor+i][2]);
            arr_Vertices[iPos + 1].position = D3DMXVECTOR3( arrV[j*iFactor+iNext][0], arrV[j*iFactor+iNext][1], arrV[j*iFactor+iNext][2]);


            if (j != iFactor -1)
                arr_Vertices[iPos + 2].position = D3DMXVECTOR3( arrV[((j+1)*iFactor)+i][0], arrV[((j+1)*iFactor)+i][1], arrV[((j+1)*iFactor)+i][2]);
            else
                arr_Vertices[iPos + 2].position = D3DMXVECTOR3( 0, 0, -1); //Create a pseudo triangle fan for the last set of triangles

            arr_Vertices[iPos].normal = D3DMXVECTOR3( arr_Vertices[iPos].position.x, arr_Vertices[iPos].position.y, arr_Vertices[iPos].position.z);
            arr_Vertices[iPos + 1].normal = D3DMXVECTOR3( arr_Vertices[iPos+1].position.x, arr_Vertices[iPos+1].position.y, arr_Vertices[iPos+1].position.z);
            arr_Vertices[iPos + 2].normal = D3DMXVECTOR3( arr_Vertices[iPos+2].position.x, arr_Vertices[iPos+2].position.y, arr_Vertices[iPos+2].position.z);

            arr_Vertices[iPos + 3].position = D3DMXVECTOR3( arr_Vertices[iPos+2].position.x, arr_Vertices[iPos+2].position.y, arr_Vertices[iPos+2].position.z);
            arr_Vertices[iPos + 4].position = D3DMXVECTOR3( arr_Vertices[iPos+1].position.x, arr_Vertices[iPos+1].position.y, arr_Vertices[iPos+1].position.z);

            if (j != iFactor - 1)
                arr_Vertices[iPos + 5].position = D3DMXVECTOR3( arrV[((j+1)*iFactor)+iNext][0], arrV[((j+1)*iFactor)+iNext][1], arrV[((j+1)*iFactor)+iNext][2]);
            else
                arr_Vertices[iPos + 5].position = D3DMXVECTOR3( 0,0,-1);

            arr_Vertices[iPos + 3].normal = D3DMXVECTOR3( arr_Vertices[iPos+3].position.x, arr_Vertices[iPos+3].position.y, arr_Vertices[iPos+3].position.z);
            arr_Vertices[iPos + 4].normal = D3DMXVECTOR3( arr_Vertices[iPos+4].position.x, arr_Vertices[iPos+4].position.y, arr_Vertices[iPos+4].position.z);
            arr_Vertices[iPos + 5].normal = D3DMXVECTOR3( arr_Vertices[iPos+5].position.x, arr_Vertices[iPos+5].position.y, arr_Vertices[iPos+5].position.z);

            //std::cout << "[" << iPos <<"] = " << arr_Vertices[iPos].position.x << 
            //  "," << arr_Vertices[iPos].position.y <<
            //  "," << arr_Vertices[iPos].position.z <<std::endl;

            //std::cout << "[" << iPos + 1 <<"] = " << arr_Vertices[iPos + 1].position.x << 
            //  "," << arr_Vertices[iPos+ 1].position.y <<
            //  "," << arr_Vertices[iPos+ 1].position.z <<std::endl;

            //std::cout << "[" << iPos + 2 <<"] = " << arr_Vertices[iPos].position.x << 
            //  "," << arr_Vertices[iPos + 2].position.y <<
            //  "," << arr_Vertices[iPos + 2].position.z <<std::endl;
        }
    }
}

应该是只有少数的调整使用。这将创建一个TRIANGLELIST但可以改变输出一组三角形条

Should be usable with only a few adjustments. This creates a TRIANGLELIST but could be altered to output a set of triangle strips

推荐答案

考虑这个问题的基本方式:

Basic way of thinking about it:

不使用连续的三角形带第一种方法......

First method not using a continuous triangle strip...

这已经有一段时间,所以我可能犯了一个错误...

It's been a while so I might make a mistake...

一个单位圆定义参: 其中0 =&其中; THETA&LT;二皮 X = SIN(THETA); Y = COS(THETA);

A unit circle defined parametrically: Where 0 =< theta < 2pi x = sin(theta); y = cos(theta);

现在,我们可以定义一个圆圈,想象同心环在x,y平面。 现在想象一下提高了内心最圆,你要再它拉了下环,像紧身...这个可视化只适用于半个球体。

Now that we can define a single circle, imagine concentric rings on the x,y plane. Now imagine raising the inner most circle and as you raise it it pulls up the next ring, like a slinky... This visual only works for half a sphere.

因此​​,产生的球的形状从同心环的形式是当然的另一个圆是垂直于环中,(Z,Y)平面...当然,我们只关心的查找偏移环(如何高或低,它需要从(X,Y)平面偏移。

So the form that produces the shape of a sphere from the concentric rings is of course another circle which is orthogonal to the rings, the (z,y) plane... Of course we are only interested in finding the offset of the ring (how high or low it needs to be offset from the (x,y) plane.

由于我们只需要补偿我们只需要半圈......,进一步两极只会是一个点。使用三角形扇的极点和各条环之间。

Because we just need the offset we only need half a circle... and further the poles will only be a single point. Use a triangle fan at the poles and strips between each ring.

这种心理练习后看到 http://en.wikipedia.org/wiki/Sphere 并搜索在半径为r的球的点可以通过被参数化和该行后,你会看到参数表。

After this mental exercise see http://en.wikipedia.org/wiki/Sphere and search for "The points on the sphere with radius r can be parametrized via" and you'll see the parametric form after that line.

的法线非常容易球体应始终围绕(0,0,0)和球体应始终为1(这样可以简单地将其扩展到所需的大小)的半径建造,然后每个顶点圆上的表面是等于正常

The normals are very easy the sphere should always be built around (0,0,0) and the sphere should always be built with a radius of 1 (so you can simply scale it to the desired size) and then each vertex on the circle surface is equal to the normal.

以上方法使用两个三角形扇等一系列三角形带的......另外其产生的球体均匀分布顶点,可以用一个三角形带绘制方法,但在现阶段,我会发疯试图code它包括以下思路:

The above method uses two triangle fans and a series of triangle strips... another method which produces a sphere with an even distribution of vertexes and can be drawn with a single triangle strip, although at the moment I'd go crazy trying to code it involves the following idea:

想象为中心原点的四面体(点为1个单位,从0,0,0)。这是一个pretty的可怜重新$ P $球体psentation,但它是一个近似值。现在,假设我们发现在每四个面的中点,然后按该点,直至其脱离的球的表面上。随后,我们发现这些面的中点并将它们推出到球体的表面...

Imagine a tetrahedron centered about the origin (the points are 1 unit from 0,0,0). It is a pretty pathetic representation of a sphere but it is an approximation. Now imagine that we find the midpoint on each of the four faces and then push that point out until it is on the surface of the sphere. Then we find the midpoints of those faces and push them out to the surface of the sphere...

tetrahdralSphere(INT递归){}

tetrahdralSphere(int recursions){}

查找的中点是非常简单,它是每一个在x,y,z分量的只是平均。然后,因为球是一个单位球面将它们转移到表面很简单,只要正常化这一新的载体。

Finding the mid point is very simple it is just the average of each of the x,y,z components. Then since the sphere is a unit sphere moving them to the surface is as simple as normalizing this new vector.

方法一产生,看起来经度和纬度线,并产生一个非均匀分布(它,如果用四边形和线框看起来就像一个地球仪)一个点分布,这是很容易实现。第二种方法需要递归所以它有点困难,但看起来更均匀。如果你想获得真正复杂而伤害你的头......然后尝试分配n个点,然后模拟点之间的排斥力而移动它们分开,然后在表面上归他们。有各种各样的需要头疼解决有效,使这项工作,但那么你已经相当均匀分布的点,你可以控制顶点的数目,你就会有有什么需要的AP preciation劈头建模工具来寻找最小的几何形状,重新present的典范。

Method one produces a point distribution that looks lines of longitude and latitude and produces a non uniform distribution (it looks just like a globe if using quads and a wire frame), it is quite easy to implement. The second method requires recursion so it a little more difficult but will look more uniform. If you want to get really complicated and hurt your head... then try distributing n points and then simulate a repellent force between points which moves them apart and then normalize them across the surface. There are all kinds of headaches that need to addressed to make this work effectively but then you have rather uniformly distributed points and you can control the number of vertices's and you'll have have the very start of appreciation of what it takes for modeling tools to find the minimal geometry to represent a model.

去与第一种方法。 画一个点(0,0,1),那么你需要你的第一个同心环(每环将有简单的分数相同的)。

Going with the first method. Draw a point at (0,0,1) then you need your first concentric ring (each ring will have the same number of points for simplicity).

让每圈画出10个点...所以披将于二皮增量步/ 10 并让画10同心圆

Lets draw 10 points per ring... so phi will step in increments of 2pi/10 and lets draw 10 concentric rings

和我们将绘制10圈+ 2电线杆那么THETA将PI / 12的增量增加。

and we will draw 10 rings + 2 poles so theta will increase in increments of pi/12.

//this psudo code places the points
//NOT TESTED
deltaTheta = pi/12;
deltaPhi = 2pi/10;
drawVertex(0,0,1) //north pole end cap
for(int ring; ring < 10; ring++){ //move to a new z - offset 
  theta += deltaTheta;
  for(int point; point < 10; point++){ // draw a ring
    phi += deltaPhi;
    x = sin(theta) * cos(phi)
    y = sin(theta) * sin(phi)
    z = cos(theta)
    drawVertex(x,y,z)
  }
}
drawVertex(0, 0, -1) //south pole end cap