Question

I have a basic program that draws a cube out of 48 tetrahedrons. More precisely it uses 27 vertices and an index buffer to draw these tetrahedrons. I would like to apply a texture to all of the tetrahedrons but all of the tutorials I found about textures don't render using indices and every vertex in my program is used in 16 other tetrahedrons so i can't even figure out how to orient the textures. The program itself is too long and too messy for me to post it but If someone could please tell me whether it's possible to put textures onto indexed primitives or not and also give me a link to a tutorial I would be grateful.

EDIT: Code ici:

void setVertices(FLOAT cubeYOffset, FLOAT cubeXOffset, FLOAT cubeZOffset, int tetraRender[]){
CUSTOMVERTEX vertices[] = { 
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, },//Center top = 0
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, -0.5f, 0.5f, 0.0f, -1.0f, 1.0f, },
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 1.0f, },
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, },
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, 0.0f, 0.5f, -0.5f, 0.0f, 1.0f, },
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, },

    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, },//Center middle = 9
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, },
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, -0.5f, 0.0f, 0.5f, -1.0f, 0.0f, },
    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, 0.5f, 0.0f, -0.5f, 1.0f, 0.0f, },
    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, },
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, -0.5f, 0.0f, -0.5f, -1.0f, 0.0f, },

    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, },//Center bottom = 18
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, -0.5f, -0.5f, 0.0f, -1.0f, -1.0f, },
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, -0.5f, -0.5f, 0.5f, -1.0f, -1.0f, },
    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, 0.0f, -0.5f, 0.5f, 0.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, 0.5f, -0.5f, 0.5f, 1.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, 0.5f, -0.5f, -0.5f, 1.0f, -1.0f, },
    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, 0.0f, -0.5f, -0.5f, 0.0f, -1.0f, },
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, },//26(actually 27th)
};
d3ddev->CreateVertexBuffer(27*sizeof(CUSTOMVERTEX),
                           0,
                           CUSTOMFVF,
                           D3DPOOL_MANAGED,
                           &v_buffer,
                           NULL);

VOID* pVoid;
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();

short tetra[48][12] = {
    //tetra 1
    0, 1, 2,
    0, 1, 11,
    0, 2, 11,
    1, 2, 11,

    //tetro 2
    0, 2, 3,
    0, 2, 11,
    0 , 3, 11,
    2, 3, 11,

    //tetro 3
    0, 3, 4,
    0, 3, 13,
    0, 4, 13,
    3, 4, 13,

    //tetro 4
    0, 4, 5,
    0, 4, 13,
    0, 5, 13,
    4, 5, 13,

    //tetro 5
    0, 5, 6,
    0, 5, 15,
    0, 6, 15,
    5, 6, 15,

    //tetro 6
    0, 6, 7,
    0, 6, 15,
    0, 7, 15,
    6, 7, 15,

    //tetro 7
    0, 7, 8,
    0, 7, 17,
    0, 8, 17,
    7, 8, 17,

    //tetro 8
    0, 8, 1,
    0, 8, 17,
    0, 1, 17,
    8, 1, 17,

    //tetro 9
    0, 1, 11,
    0, 1, 10,
    0, 10, 11,
    1, 10, 11,

    //tetro 10
    0, 3, 11,
    0, 3, 12,
    0, 11, 12,
    3, 11, 12,

    //tetro 11
    0, 3, 13,
    0, 3, 12,
    0, 12, 13,
    3, 12, 13,

    //tetro 12
    0, 5, 13,
    0, 5, 14,
    0, 13, 14,
    5, 13, 14,

    //tetro 13
    0, 5, 15,
    0, 5, 14,
    0, 14, 15,
    5, 14, 15,

    //tetro 14
    0, 7, 15,
    0, 7, 16,
    0, 15, 16,
    7, 15, 16,

    //tetro 15
    0, 7, 17,
    0, 7, 16,
    0, 16, 17,
    7, 16, 17,

    //tetro 16
    0, 1, 17,
    0, 1, 10,
    0, 17, 10,
    1, 17, 10,

    //tetro 17
    0, 10, 11,
    0, 9, 10,
    0, 9, 11,
    9, 10, 11,

    //tetro 18
    0, 11, 12,
    0, 9, 11,
    0, 9, 12,
    9, 11, 12,

    //tetro 19
    0, 12, 13,
    0, 9, 12,
    0, 9, 13,
    9, 12, 13,

    //tetro 20
    0, 13, 14,
    0, 9, 13,
    0, 9, 14,
    9, 13, 14,

    //tetro 21
    0, 14, 15,
    0, 9, 14,
    0, 9, 15,
    9, 14, 15,

    //tetro 22
    0, 15, 16,
    0, 9, 15,
    0, 9, 16,
    9, 15, 16,

    //tetro 23
    0, 16, 17,
    0, 9, 16,
    0, 9, 17,
    9, 16, 17,

    //tetro 24
    0, 17, 10,
    0, 9, 17,
    0, 9, 10,
    9, 17, 10,

    //tetro 17
    9, 10, 11,
    9, 18, 10,
    9, 18, 11,
    18, 10, 11,

    //tetro 18
    9, 11, 12,
    9, 18, 11,
    9, 18, 12,
    18, 11, 12,

    //tetro 19
    9, 12, 13,
    9, 18, 12,
    9, 18, 13,
    18, 12, 13,

    //tetro 20
    9, 13, 14,
    9, 18, 13,
    9, 18, 14,
    18, 13, 14,

    //tetro 21
    9, 14, 15,
    9, 18, 14,
    9, 18, 15,
    18, 14, 15,

    //tetro 22
    9, 15, 16,
    9, 18, 15,
    9, 18, 16,
    18, 15, 16,

    //tetro 23
    9, 16, 17,
    9, 18, 16,
    9, 18, 17,
    18, 16, 17,

    //tetro 24
    9, 17, 10,
    9, 18, 17,
    9, 18, 10,
    18, 17, 10,

    //tetro 9
    18, 19, 11,
    18, 19, 10,
    18, 10, 11,
    19, 10, 11,

    //tetro 10
    18, 21, 11,
    18, 21, 12,
    18, 11, 12,
    21, 11, 12,

    //tetro 11
    18, 21, 13,
    18, 21, 12,
    18, 12, 13,
    21, 12, 13,

    //tetro 12
    18, 23, 13,
    18, 23, 14,
    18, 13, 14,
    23, 13, 14,

    //tetro 13
    18, 23, 15,
    18, 23, 14,
    18, 14, 15,
    23, 14, 15,

    //tetro 14
    18, 25, 15,
    18, 25, 16,
    18, 15, 16,
    25, 15, 16,

    //tetro 15
    18, 25, 17,
    18, 25, 16,
    18, 16, 17,
    25, 16, 17,

    //tetro 16
    18, 19, 17,
    18, 19, 10,
    18, 17, 10,
    19, 17, 10,

    //tetro 19
    18, 19, 20,
    18, 19, 11,
    18, 20, 11,
    19, 20, 11,

    //tetro 20
    18, 20, 21,
    18, 20, 11,
    18 , 21, 11,
    20, 21, 11,

    //tetro 21
    18, 21, 22,
    18, 21, 13,
    18, 22, 13,
    21, 22, 13,

    //tetro 22
    18, 22, 23,
    18, 22, 13,
    18, 23, 13,
    22, 23, 13,

    //tetro 23
    18, 23, 24,
    18, 23, 15,
    18, 24, 15,
    23, 24, 15,

    //tetro 24
    18, 24, 25,
    18, 24, 15,
    18, 25, 15,
    24, 25, 15,

    //tetro 25
    18, 25, 26,
    18, 25, 17,
    18, 26, 17,
    25, 26, 17,

    //tetro 26
    18, 26, 19,
    18, 26, 17,
    18, 19, 17,
    26, 19, 17,
};
short indices [576];
int i = 0;
int i2 = 0;
ind = 0;
int ic;
for(i; i < 48; i++){
    if (tetraRender[i] == 1){
        for(i2; i2 < 12; i2++){     
            if((ind == 0)&&(i2 == 0)){ 
                ic = 0;
            }else{
                ic = ind*12+i2;
            }
            indices[ic] = tetra[i][i2]; 
        }
        i2 = 0;
        ind++;
    }
}

if (ind > 0) {
d3ddev->CreateIndexBuffer(12*ind*sizeof(short),
                            0,
                            D3DFMT_INDEX16,
                            D3DPOOL_MANAGED,
                            &i_buffer,
                            NULL);
i_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, indices, 12*ind*2);
i_buffer->Unlock();
}
    }

Ok so thats the declaration of the vertices and indices just to give you an idea. Its very messy so I'm sorry and if you can't see what it does is declare a spiral-like set of vertices followed by the declaration of all of the indices of the tetrahedrons. then it uses the int array in the from the function to draw only specified tetrahedrons.

And yes I am using 3D lighting even though I haven't the fainest why.

Was it helpful?

Solution

You're not supposed to use the FVF system anymore. Use the IDirect3DVertexDeclaration9 system, which is far more actually flexible. The problem with FVF is that when you set the flags together, the order is unspecifiable, whereas the VERTEXELEMENT9[] system is capable of specifying the order of elements as well as which ones are contained within.

The simple answer of how to generate the texture co-ordinates is pretty simple- when you consider a vertex, then it's position in 3D space and thus ultimately it's texture co-ordinates are fixed, regardless of which triangle it actually ends up a part of. Thus, unless you intend to emulate some very sharp edges, in which case you should duplicate vertices, it's perfectly acceptable to have one tex-coord per vertex with no more effort.

As for rendering the system without crashing, then it's time to use a shader, basically because fixed-function is dead and almost all modern rendering uses shaders, and you have to have learned this stuff a long time ago to know how to use it. Fortunately, basic texturing is basic and won't require anything particularly advanced.

D3DVERTEXELEMENT9 vertexDecl[] = {
    { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
    { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
    { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
    D3DDECL_END()
};
struct CustomVertex {
    float position[3];
    float normal[3];
    float texcoords[2];
};

IDirect3DVertexDeclaration9* vertexdecl;
d3ddev->CreateVertexDeclaration(vertexDecl, &vertexdecl);

And as for the shader, then something pretty simple will do.

// Stuff we send to the shader from C++
// This is not per-vertex. Anything we loaded into the 
// vertex data itself is input to the vertex shader.
// Direct3D 9.0c also supports hardware instancing, but I'll
// leave you to work that one out yourself.

// World * View * Projection matrix gives the result in Homogenous Clip 
// Co-ordinates, which is what Direct3D wants from us as output
uniform extern float4x4 WVPMatrix;
// WorldInverseTranspose transforms the normal into world space
// successfully, even with non-linear transformations as the World
uniform extern float4x4 WorldInverseTransposeMatrix;
// This is just a 2D texture that we can change at any time
uniform extern texture MyTexture;
// The sampler state determines how the texture is filtered.
sampler TexS = sampler_state
{
    Texture = <MyTexture>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};
// What we output from the vertex shader. This is basically the position
// of the vertex in HCC (the first two), and anything we want to pass into
// the pixel shader (the second two).
struct VS_OUTPUT {
    float4 position : POSITION0;
    float3 normal : NORMAL0;
    float2 texcoords : TEXCOORD0;
};
// What we're putting in to the vertex shader. This is basically
// our vertex structure from C++.
struct VS_INPUT {
    float3 position : POSITION0;
    float3 normal : NORMAL0;
    float2 texcoords : TEXCOORD0;
};
VS_OUTPUT VertexShader(VS_INPUT in) {
    VS_OUTPUT out = (VS_OUTPUT)0;
    // just pass texcoords on, we're not interested
    out.texcoords = in.texcoords;
    // get the resulting vertex position that we need
    out.position = mul(float4(in.position, 1.0f), WVPMatrix);
    // transform the normal into world space
    out.normal = mul(float4(in.normal, 0.0f), WorldInverseTransposeMatrix).xyz;
}
float4 PixelShader(float3 normal : NORMAL0, float2 texcoords : TEXCOORD0) {
    return tex2D(TexS, texcoords);
}
technique BasicShader 
{
    pass p0
    {            
        vertexShader = compile vs_3_0 VertexShader();
        pixelShader  = compile ps_3_0 PixelShader();
    }
}

I didn't do any lighting calculations here but I did pass the normal into the pixel shader.

OTHER TIPS

I'm by no means a DirectX expert, but speaking out of experience, I assume that it uses an approach very similar to OpenGL.

If you want to texture an object, you need texture coordinates for each vertex, in addition to the position attribute and possibly others (normal, tangent vector, ...). As you use an index buffer to address vertex data, I assume you have the latter in a vertex buffer. So, by adding texture coordinates to each vertex, you can wrap a texture onto your tetrahedrons. Note however, that you can't have different texture coordinates for each vertex, if your index buffer says 'I want a triangle from index 0, 1 and 2', you will always get both position and texture coordinate data from indices 0, 1, 2.

What you could do is modify the texture coordinates for each tetrahedron as whole, by applying a transformation matrix to them first. This transformation is separate from the transformation you apply to your position attributes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top