DIRECTX11 Geometry Sample Demo

Source: Internet
Author: User
DirectX11 Geometry Sample Demo

We'll describe how to build the other two geometry shapes: cylinder and spheres. These shapes are useful for sky boxes, debugging, visual collision detection, and reduced rendering. For example, you might want to have all of your game characters rendered as a sphere to debug your tests. 1. How to create a cylindrical mesh.

We divide the cylinder into three parts: the side, the top round cover and the bottom round cover. (Note that the cylinder here is not a simple cylinder, it can also refer to the Round table, cone.) When top radius of 0 is the cone. We can define a cylinder by specifying its bottom and top radii, as well as the height, and the number of slices (Slide) and layers (stacks). As shown in the following illustration:

(The left-hand cylinder has 8 slices, 4 layers.) The number of slices and the number of layers can control the density of triangles. ) 2. How to create a cylindrical side mesh.

The figure above has a "layer +1" ring, with each ring having a number of vertices.
The RADIUS difference R for each two consecutive rings is:

r = (Top circle cap radius-bottom Circle cap radius)/number of layers

If the subscript of the bottom ring is 0, then the first ring radius r (i):

R (i) = bottom ring radius + iδr.

H is the height of the layer and h is the height of the cylinder. Then the height h (i) of the first ring is:

H (i) =-H/2 + I h

So our basic implementation is to iterate each loop to produce the vertices on each ring.

So how do you specify an index?

In the following illustration, each slice in each layer has a four-sided shape (two triangles). The following figure shows the section J in layer I:

(vertex a,b,c,d contains the section J in layer I)

δabc= (i n+j, (i+1) n+j), (i+1) n+j+1)
Δacd= (i n+j, (i+1) n+j+1, I n+j+1

n is the number of vertices for each ring. Therefore, the key idea of creating an index cache is to apply the above formula to each slice in each layer.

Attention:
1. The first and last vertices of each ring are repeated in position, but the texture coordinates are not duplicated. We have to do this in order to use textures correctly.
2. The code contains additional vertex data for creating cylinder objects, such as normals and texture coordinates, which are handy for future demonstrations, and don't worry about the code now.
3. Create a cylindrical side grid source code

void Geometrygenerator::createcylinder (float Bottomradius, float topradius, float height, uint slicecount, uint
    Stackcount, meshdata& meshdata) {meshData.Vertices.clear ();

    MeshData.Indices.clear ();

    Build Layer//float stackheight = Height/stackcount;

    Depending on the level of the layer, the step from bottom up increases the radius of float Radiusstep = (topradius-bottomradius)/stackcount;

    UINT ringcount = stackcount+1;
        Bottom up calculates the vertex for each layer ring for (UINT i = 0; i < Ringcount; ++i) {Float y = -0.5f*height + i*stackheight;

        float R = Bottomradius + i*radiusstep;
        The vertex of the ring float Dtheta = 2.0f*xm_pi/slicecount;

            for (UINT j = 0; J <= Slicecount; ++j) {Vertex Vertex;
            float c = COSF (J*dtheta);

            float s = sinf (J*dtheta); Vertex.

            Position = XMFLOAT3 (R*c, y, r*s); Vertex.
            texc.x = (float) j/slicecount; Vertex.

            TEXC.Y = 1.0f-(float) i/stackcount; Vertex. Tangentu = XmfloaT3 (-S, 0.0f, C);
            Float dr = Bottomradius-topradius;

            XMFLOAT3 bitangent (Dr*c,-height, dr*s); Xmvector T = XMLOADFLOAT3 (&vertex.
            Tangentu);
            Xmvector B = XMLOADFLOAT3 (&bitangent);
            Xmvector N = xmvector3normalize (Xmvector3cross (T, B)); XMSTOREFLOAT3 (&vertex.

            Normal, N);
        MeshData.Vertices.push_back (vertex);

    }}//Because the mapping coordinates of the first vertex and the last vertex are different, we add 1 UINT ringvertexcount = slicecount+1 to the vertex number;
            Compute vertices for each layer for (uint i = 0; i < Stackcount; ++i) {for (uint j = 0; j < Slicecount; ++j) {
            MeshData.Indices.push_back (I*ringvertexcount + j);
            MeshData.Indices.push_back ((i+1) *ringvertexcount + j);

            MeshData.Indices.push_back ((i+1) *ringvertexcount + j+1);
            MeshData.Indices.push_back (I*ringvertexcount + j);
            MeshData.Indices.push_back ((i+1) *ringvertexcount + j+1); MeshData.Indices.push_back (I*rinGvertexcount + j+1); }}//The following two function calls produce the top circle cover and the bottom circle cover grid, and then we'll talk about Buildcylindertopcap (Bottomradius, Topradius, height, slicecount, Stackcoun
    T, Meshdata);
Buildcylinderbottomcap (Bottomradius, Topradius, height, slicecount, Stackcount, Meshdata); }
4. How to produce a mesh with a cylindrical top cover mesh and a bottom round cover grid. (source code implementation)

The principle is to produce a top ring with enough pieces to approximate a circle, we look directly at the source code, the bottom and top of the code is almost the same:

void Geometrygenerator::buildcylindertopcap (float Bottomradius, float topradius, float height, UINT Slicecount, uint stackcount, meshdata& meshdata) {UINT BaseIndex = (UINT) meshdata.vertices

    . Size ();
    Float y = 0.5f*height;

    float Dtheta = 2.0f*xm_pi/slicecount; Because the map coordinates and normal vectors of the ring vertices at the top of the cylinder are different, we want to copy the top vertex for (UINT i = 0; I <= slicecount; ++i) {Float x = Topradius*cos
        f (I*dtheta);

        float z = topradius*sinf (I*dtheta);
        Scale down by the height-to-try and make top caps texture coord area proportional to base.
        float u = x/height + 0.5f;

        Float v = z/height + 0.5f;
    MeshData.Vertices.push_back (Vertex (x, Y, Z, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, U, v)); 

    }//Cap center vertex meshData.Vertices.push_back (Vertex (0.0f, y, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f));

    Index of the center vertex UINT centerindex = (UINT) meshData.Vertices.size ()-1; for (UINT i = 0; i < Slicecount;
        ++i) {meshData.Indices.push_back (centerindex);
        MeshData.Indices.push_back (BaseIndex + i+1);
    MeshData.Indices.push_back (BaseIndex + i); }
}
void Geometrygenerator::buildcylinderbottomcap (float Bottomradius, float topradius, float height, UINT Slicecount, uint stackcount, meshdata& meshdata) {/////Set bottom cover//UINT
    BaseIndex = (UINT) meshData.Vertices.size ();

    Float y = -0.5f*height;
    The vertex of the ring float Dtheta = 2.0f*xm_pi/slicecount;
        for (UINT i = 0; I <= slicecount; ++i) {Float x = BOTTOMRADIUS*COSF (I*dtheta);

        float z = bottomradius*sinf (I*dtheta);
        Scale down by the height-to-try and make top caps texture coord area proportional to base.
        float u = x/height + 0.5f;

        Float v = z/height + 0.5f;
    MeshData.Vertices.push_back (Vertex (x, Y, Z, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, U, v)); }//Cap center vertex meshData.Vertices.push_back (Vertex (0.0f, y, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f))

    ;

    Index cache for center vertex UINT centerindex = (UINT) meshData.Vertices.size ()-1; ForUINT i = 0; i < Slicecount;
        ++i) {meshData.Indices.push_back (centerindex);
        MeshData.Indices.push_back (BaseIndex + i);
    MeshData.Indices.push_back (BaseIndex + i+1); }
}
5. How to create a sphere grid.

The book introduces two methods, one is Geometrygenerator::createsphere, the other is geometrygenerator::creategeosphere. 6. Createsphere generated sphere source code implementation

The following figure is the sphere produced by the Createsphere method.

This method is also created by specifying the number of slices and the number of layers, and the resulting algorithm is very similar to the cylinder generation algorithm, but the radius variation of each ring is based on the nonlinear transformation generated by the trigonometric functions. The triangle produced by Createsphere is not equilateral triangle, the triangles are not necessarily equal, and the triangles produced in creategeosphere form are equilateral triangle, and they are congruent triangles, which can be found in the geosphere of the next picture. Compare the differences between the two spheres of the grid. Here only the source code, not to repeat. (The non-translation of the English note is not a part of the current section of the knowledge, temporarily do not care)

void Geometrygenerator::createsphere (float radius, uint slicecount, uint stackcount, meshdata& meshdata) {Meshdat
    A.vertices.clear ();

    MeshData.Indices.clear ();
    Calculates the extreme point of the top and moves the heap down////Extreme point: Note that the mapping coordinates may be distorted because the square map maps to the sphere causing no suitable position to be mapped to the extreme point.
    Vertex Topvertex (0.0f, +radius, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);

    Vertex Bottomvertex (0.0f,-radius, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);

    MeshData.Vertices.push_back (Topvertex);
    float phistep = Xm_pi/stackcount;

    float thetastep = 2.0f*xm_pi/slicecount;

        Calculates the vertex of each stack ring (does not treat the extreme point as a ring) for (UINT i = 1; I <= stackCount-1; ++i) {Float phi = I*phistep;

            The vertex of the Ring for (UINT j = 0; J <= Slicecount; ++j) {float theta = j*thetastep;

            Vertex v;
            Spherical to Cartesian coordinate system v.position.x = Radius*sinf (phi) *COSF (theta);
            V.POSITION.Y = RADIUS*COSF (PHI); V.position.z = Radius*sinf (phi) *sInf (theta);
            Partial derivative of P with respect to theta v.tangentu.x =-radius*sinf (phi) *sinf (theta);
            V.tangentu.y = 0.0f;

            V.tangentu.z = +radius*sinf (phi) *COSF (theta);
            Xmvector T = XMLOADFLOAT3 (&v.tangentu);

            XMSTOREFLOAT3 (&v.tangentu, Xmvector3normalize (T));
            Xmvector p = XMLoadFloat3 (&v.position);

            XMSTOREFLOAT3 (&v.normal, Xmvector3normalize (p));
            v.texc.x = Theta/xm_2pi;

            V.texc.y = PHI/XM_PI;
        MeshData.Vertices.push_back (v);

    }} meshData.Vertices.push_back (Bottomvertex); The index of the computed heap.
    The top of the heap is the vertex that caches the first data, and connects the extreme points of the top to the first ring.
        for (UINT i = 1; I <= slicecount; ++i) {meshData.Indices.push_back (0);
        MeshData.Indices.push_back (i+1);
    MeshData.Indices.push_back (i); }///Calculate the index of the inside heap.
    (excluding extreme points)/////first vertex to first ring index offset//Here just skip the extreme vertex of the top UINT baseindex = 1; UINT ringvertexcount = slicecount+1; for (UINT i = 0, i < stackCount-2; ++i) {for (uint j = 0; j < Slicecount; ++j) {Mesh
            Data.Indices.push_back (BaseIndex + I*ringvertexcount + j);
            MeshData.Indices.push_back (BaseIndex + i*ringvertexcount + j+1);

            MeshData.Indices.push_back (BaseIndex + (i+1) *ringvertexcount + j);
            MeshData.Indices.push_back (BaseIndex + (i+1) *ringvertexcount + j);
            MeshData.Indices.push_back (BaseIndex + i*ringvertexcount + j+1);
        MeshData.Indices.push_back (BaseIndex + (i+1) *ringvertexcount + j+1); }}///Calculate the index of the bottom heap.

    The bottom heap is the last to write to the vertex cache, and the extreme point of the connection low end and the bottom ring//////South Extreme vertex is the last added UINT Southpoleindex = (UINT) meshData.Vertices.size ()-1;

    The offset index of the first vertex to the last ring BaseIndex = Southpoleindex-ringvertexcount;
        for (UINT i = 0; i < Slicecount; ++i) {meshData.Indices.push_back (southpoleindex);
    MeshData.Indices.push_back (Baseindex+i);    MeshData.Indices.push_back (baseindex+i+1); }
}
6. Creategeosphere generated sphere source code implementation

The following figure is the production process of geosphere. Its principle is to subdivide by a 20-facet body and then map the subdivided vertices to a sphere. You can also repeat this process to produce a higher-subdivision sphere.

We produce four small triangles by taking the midpoint of each edge of a triangle, as shown below:

At this point the vertices are all in the same plane, and then the size of all vertex position vectors is changed to the radius size (this process is equivalent to mapping all the newly created vertices of the 20 polygon to the sphere surface), resulting in a higher subdivision of the sphere.
You can change the size of the vertex position vector to a radius size by using the following formula:

Now, we have enough knowledge to look at the source code:

void Geometrygenerator::creategeosphere (float radius, UINT numsubdivisions, meshdata& meshdata) {//Put a cap on
    The number of subdivisions.

    Fine fraction numsubdivisions = mathhelper::min (numsubdivisions, 5u);
    Approximate a sphere by tessellating an icosahedron. 
    Create a sphere const float X = 0.525731f by subdividing The 20-face body;

    const float Z = 0.850651f; XMFLOAT3 pos[12] = {XMFLOAT3-X, 0.0f, z), XMFLOAT3 (x, 0.0f, z), XMFLOAT3 (-X, 0.0f,-Z), XMFLOAT3 (X, 0.0f,-Z), XMFLOAT3 (0.0f, z, x), XMFLOAT3 (0.0f, Z,-X), XMFLOAT3 (0.0f,-Z, x), XMFLOAT3 (0.0f, Z,-X), XMFLOAT3 (z, x, 0.0f), XMFLOAT3 (-Z, X, 0.0f), XMFLOAT3 (z,-X, 0.0f), XMFLOAT3 (-Z,-X, 0.0f

    )
    };    
        DWORD k[60] = {1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, 1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2,

    3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0, 10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7}; Meshdata.vertices. Resize (12);

    MeshData.Indices.resize (60); for (UINT i = 0; i <; ++i) Meshdata.vertices[i].

    Position = Pos[i];

    for (UINT i = 0; i <; ++i) meshdata.indices[i] = K[i];

    for (UINT i = 0; i < numsubdivisions; ++i) subdivide (meshdata); Cast vertex to sphere and zoom for (UINT i = 0; i < meshData.Vertices.size (); ++i) {//cast to unit ball xmvector n = X Mvector3normalize (XMLOADFLOAT3 (&meshdata.vertices[i).

        Position));

        Cast to a sphere of radius xmvector p = radius*n; XMSTOREFLOAT3 (&meshdata.vertices[i].
        Position, p); XMSTOREFLOAT3 (&meshdata.vertices[i].

        Normal, N); Export texture coordinates from spherical coordinates float theta = Mathhelper::anglefromxy (Meshdata.vertices[i]. Position.x, Meshdata.vertices[i].

        POSITION.Z); Float phi = ACOSF (Meshdata.vertices[i].

        Position.y/radius); Meshdata.vertices[i].
        texc.x = Theta/xm_2pi; Meshdata.vertices[i].

        Texc.y = PHI/XM_PI;Partial derivative of P with respect to Theta Meshdata.vertices[i].
        tangentu.x =-radius*sinf (phi) *sinf (theta); Meshdata.vertices[i].
        Tangentu.y = 0.0f; Meshdata.vertices[i].

        Tangentu.z = +radius*sinf (phi) *COSF (theta); Xmvector T = XMLOADFLOAT3 (&meshdata.vertices[i].
        Tangentu); XMSTOREFLOAT3 (&meshdata.vertices[i].
    Tangentu, Xmvector3normalize (T)); }
}
7. Shape Sample Demo

Now take a look at this demo, which will show multiple spheres and cylinders, as well as the previously used cubes. We use different world coordinate matrices to draw multiple objects.

Defines a matrix converted from a local coordinate system to a world coordinate system xmfloat4x4 msphe reworld[10]; 
xmfloat4x4 MCYLWORLD[10]; 
xmfloat4x4 Mboxworld; 
xmfloat4x4 Mgridworld; 
xmfloat4x4 mCe nte Rsphe re; 
Xmmatrix I = Xmmatrixide ntity (); 
Xmstore float4x4 (&mgridworld, I); 
Xmmatrix Boxscale = xmmatrixscaling (2.0f, 1.0f, 2.0f); 
Xmmatrix Boxoffset = xmmatrixtranslation (0.0f, 0.5f, 0.0f); 
Xmstore float4x4 (&mboxworld, xmmatrixmultiply (Boxscale, Boxoffset)); 
Xmmatrix CE nte rsphere scale = xmmatrixscaling (2.0f, 2.0f, 2.0f); 
Xmmatrix CE nte rsphere Offset = xmmatrixtranslation (0.0f, 2.0f, 0.0f); 
Xmstore float4x4 (&mce nte rsphe Re, xmmatrixmultiply (CE nte rsphe re scale, Cente Rsphe re Offset)); 
We Create 5 rows of 2 cylinders and spheres per row. for (inti=0;i<5;++i) {xmstorefloat4x4 (&mcylworld[i*2+0], xmmatrixtranslation ( -5.0f, 1.5f, -10.0f + i 
    *5.0f)); 
    xmstorefloat4x4 (&mcylworld[i*2+1], xmmatrixtranslation (+5.0f, 1.5f, -10.0f + i*5.0f)); xmstorefloat4x4 (&msphere World[i*2+0], xmmatrixtranslation ( -5.0f, 3.5f, -10.0f + i* 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.