Une classe pour afficher des lignes en 3D avec une certaine couleur

3D_lines

Intro :

Il peut être utile d’afficher des lignes dans la surface de rendu ; par exemple pour représenter des normales, des trajectoires, un repère, etc…

Prérequis :

– Savoir lire du C++

– Savoir utiliser la classe MeshSceneNode

– Savoir utiliser la classe ShaderTechnique et les déclarations de vertices.

Explications :

Voici le fichier Vertex3DLine.h :

#ifndef MESH_3D_LINE_H
#define MESH_3D_LINE_H

class Vertex3DLine : public MeshSceneNode
{
public:
    Vertex3DLine(unsigned int bufferBytesSize);
    virtual ~Vertex3DLine();

    bool Initialize();

    void AddLine(D3DXVECTOR3 startPoint, D3DXVECTOR3 endPoint, D3DXCOLOR color);

private:
    void ResizeVertexBuffer(unsigned int iNewBytesSize);

private:
    std::vector<PCVertex> m_vertices;

    unsigned int m_bufferBytesSize;
};

#endif

 

Voici le fichier Vertex3DLine.cpp :

#include "Vertex3DLine.h"

Vertex3DLine::Vertex3DLine(unsigned int bufferBytesSize) :
m_bufferBytesSize(bufferBytesSize)
{
    SetVertexType(VertexLayoutType::PC_VERTEX);
    SetDrawMethod(DrawMethod::DRAW_NORMAL);
    SetTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST);

    SetShaderTechnique( SHADER_MANAGER->GetShader("Vertex3DLine") );
}

Vertex3DLine::~Vertex3DLine()
{
    m_vertices.clear();
}

bool Vertex3DLine::Initialize()
{
    HRESULT hr;

    D3D10_BUFFER_DESC bd;
    bd.Usage = D3D10_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(PCVertex) * m_bufferBytesSize;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    bd.MiscFlags = 0;

    hr = D3D10_RENDERER->GetDevice()->CreateBuffer(&bd, 0, &m_pVertexBuffer);

    if (FAILED(hr))
    {
        ShowMessageBoxDXError(hr);
        return false;
    }

    return true;
}

void Vertex3DLine::AddLine(D3DXVECTOR3 startPoint, D3DXVECTOR3 endPoint, D3DXCOLOR color)
{
    if (!m_pVertexBuffer)
    {
        return;
    }

    D3D10_BUFFER_DESC bd;
    m_pVertexBuffer->GetDesc(&bd);

    unsigned int iActualBufferBytesSize = bd.ByteWidth;
    unsigned int iNewBufferBytesSize = (m_vertices.size() + 2) * sizeof(PCVertex);

    // Si la taille du buffer est trop petite pour ajouter de nouveaux éléments
    // => on redimensionne
    if (iNewBufferBytesSize > iActualBufferBytesSize)
    {
        ResizeVertexBuffer(iActualBufferBytesSize + 2);
    }

    PCVertex* data = nullptr;

    PCVertex vert1;
    PCVertex vert2;

    vert1.position = startPoint;
    vert1.color = color;

    vert2.position = endPoint;
    vert2.color = color;

    m_vertices.push_back(vert1);
    m_vertices.push_back(vert2);

    m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&data);

    memcpy(data, m_vertices.data(), sizeof(PCVertex) * m_vertices.size());

    m_pVertexBuffer->Unmap();

    m_iVerticesCount = m_vertices.size();
}

void Vertex3DLine::ResizeVertexBuffer(unsigned int iNewBytesSize)
{
    SAFE_RELEASE(m_pVertexBuffer);

    HRESULT hr;

    D3D10_BUFFER_DESC bd;
    bd.Usage = D3D10_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(PCVertex) * iNewBytesSize;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    bd.MiscFlags = 0;
    hr = D3D10_RENDERER->GetDevice()->CreateBuffer(&bd, nullptr, &m_pVertexBuffer);

    if (FAILED(hr))
    {
        ShowMessageBoxDXError(hr);
    }
}

 

Voici le fichier ShaderTechnique_Vertex3DLine.h :

//------------------------------------------------------
// Shader d'affichage de lignes 3D
//------------------------------------------------------
class Vertex3DShaderTechnique : public ShaderTechnique
{
public:
    Vertex3DShaderTechnique();
    virtual ~Vertex3DShaderTechnique();

    virtual bool Initialize();

    virtual void SetupShaderVariables();

    virtual void Update(float fTimeSinceLastFrame);

};

 

Voici le fichier ShaderTechnique_Vertex3DLine.cpp :

#include "ShaderTechnique_Vertex3DLine.h"

Vertex3DShaderTechnique::Vertex3DShaderTechnique() :
ShaderTechnique("3DLine.fx", "Render", VertexLayoutType::PC_VERTEX)
{
}

Vertex3DShaderTechnique::~Vertex3DShaderTechnique()
{
}

bool Vertex3DShaderTechnique::Initialize()
{
    ShaderTechnique::Initialize();

    SetupShaderVariables();

    return true;
}

void Vertex3DShaderTechnique::SetupShaderVariables()
{
    RegisterMatrixVariable("World", ShaderVariableType::WORLD);
    RegisterMatrixVariable("View", ShaderVariableType::VIEW);
    RegisterMatrixVariable("Projection", ShaderVariableType::PROJECTION);
}

void Vertex3DShaderTechnique::Update(float fTimeSinceLastFrame)
{
    SetAutoMatrix(ShaderVariableType::WORLD);
    SetAutoMatrix(ShaderVariableType::VIEW);
    SetAutoMatrix(ShaderVariableType::PROJECTION);
}

 

Voici le fichier 3DLine.fx correspondant :

matrix World;
matrix View;
matrix Projection;

struct VS_INPUT
{
    float4 Pos : POSITION;
    float4 Color : COLOR0;
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR0;
};

PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    
    output.Pos = mul( input.Pos, World );
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );
    
    output.Color = input.Color;
    
    return output;
}

float4 PS( PS_INPUT input) : SV_Target
{
    return input.Color;
}

technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

 

Résumé :

Nous avons présenté un système permettant d’afficher des lignes dans la surface de rendu tout en pouvant spécifier leur couleur.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *