374 lines
15 KiB
MQL5
374 lines
15 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| DXMesh.mqh |
| |||
//| Copyright 2000-2025, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
| |||
#property link "https://www.mql5.com"
| |||
#include "DXObject.mqh"
| |||
#include "DXDispatcher.mqh"
| |||
#include "DXData.mqh"
| |||
#include "DXUtils.mqh"
| |||
//+------------------------------------------------------------------+
| |||
//| DX simple mesh object with default shader |
| |||
//+------------------------------------------------------------------+
| |||
class CDXMesh : public CDXObject
| |||
{
| |||
protected:
| |||
//--- DX resources
| |||
CDXVertexBuffer* m_buffer_vertex;
| |||
CDXIndexBuffer* m_buffer_index;
| |||
CDXInput* m_buffer_object;
| |||
CDXInput* m_buffer_scene;
| |||
CDXShader* m_shader_vertex;
| |||
CDXShader* m_shader_pixel;
| |||
CDXTexture* m_texture;
| |||
//--- object data
| |||
DXMatrix m_transform_matrix;
| |||
DXColor m_diffuse_color;
| |||
DXColor m_emission_color;
| |||
DXColor m_specular_color;
| |||
float m_specular_power;
| |||
| |||
ENUM_DX_PRIMITIVE_TOPOLOGY m_topology;
| |||
| |||
public:
| |||
//+------------------------------------------------------------------+
| |||
//| Constructor |
| |||
//+------------------------------------------------------------------+
| |||
CDXMesh(void):m_buffer_vertex(NULL),m_buffer_index(NULL),m_buffer_object(NULL),m_buffer_scene(NULL),m_shader_vertex(NULL),m_shader_pixel(NULL),m_topology(WRONG_VALUE)
| |||
{
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Destructor |
| |||
//+------------------------------------------------------------------+
| |||
~CDXMesh(void)
| |||
{
| |||
Shutdown();
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Create mesh object from vertices and indices list |
| |||
//+------------------------------------------------------------------+
| |||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVertex &vertices[],const uint &indices[],ENUM_DX_PRIMITIVE_TOPOLOGY topology=DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
| |||
{
| |||
Shutdown();
| |||
//--- check data
| |||
if(buffer_scene==NULL || buffer_scene.Handle()==INVALID_HANDLE ||
| |||
ArraySize(vertices)<1 || ArraySize(indices)<1)
| |||
return(false);
| |||
//--- update context
| |||
m_context=dispatcher.DXContext();
| |||
//--- initialize default parameters
| |||
DXMatrixIdentity(m_transform_matrix);
| |||
m_diffuse_color =DXColor(1.0,1.0,1.0,1.0);
| |||
m_emission_color=DXColor(0.0,0.0,0.0,0.0);
| |||
m_specular_color=DXColor(0.0,0.0,0.0,0.0);
| |||
m_specular_power=16.0f;
| |||
//--- create object input
| |||
m_buffer_object=dispatcher.InputCreate<DXInputObject>();
| |||
if(m_buffer_object!=NULL)
| |||
{
| |||
m_buffer_object.AddRef();
| |||
//--- use default vertex shader
| |||
m_shader_vertex=dispatcher.ShaderCreateDefault(DX_SHADER_VERTEX);
| |||
if(m_shader_vertex!=NULL)
| |||
{
| |||
m_shader_vertex.AddRef();
| |||
//--- use default pixel shader
| |||
m_shader_pixel=dispatcher.ShaderCreateDefault(DX_SHADER_PIXEL);
| |||
if(m_shader_pixel!=NULL)
| |||
{
| |||
m_shader_pixel.AddRef();
| |||
//--- create vertex buffer
| |||
m_buffer_vertex=dispatcher.VertexBufferCreate(vertices);
| |||
if(m_buffer_vertex!=NULL)
| |||
{
| |||
m_buffer_vertex.AddRef();
| |||
//--- create index buffer
| |||
m_buffer_index=dispatcher.IndexBufferCreate(indices);
| |||
if(m_buffer_index!=NULL)
| |||
m_buffer_index.AddRef();
| |||
}
| |||
}
| |||
}
| |||
}
| |||
//--- set object buffer to shaders
| |||
if(m_buffer_object==NULL || m_shader_vertex==NULL || m_shader_pixel==NULL || m_buffer_vertex==NULL || m_buffer_index==NULL)
| |||
{
| |||
Shutdown();
| |||
return(false);
| |||
}
| |||
//--- save scene buffer
| |||
m_buffer_scene=buffer_scene;
| |||
m_buffer_scene.AddRef();
| |||
//--- save topology
| |||
m_topology=topology;
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Create mesh object from OBJ mesh file |
| |||
//+------------------------------------------------------------------+
| |||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,string obj_path,float scale=1.0f,bool inverse_winding=false)
| |||
{
| |||
DXVertex vertices[];
| |||
uint indices[];
| |||
//--- load model
| |||
if(!DXLoadObjModel(obj_path,vertices,indices,scale))
| |||
return(false);
| |||
//--- set white vertices color
| |||
int count=ArraySize(vertices);
| |||
for(int i=0; i<count; i++)
| |||
vertices[i].vcolor=DXColor(1.0f,1.0f,1.0f,1.0f);
| |||
//--- inverse winding
| |||
if(inverse_winding)
| |||
DXInverseWinding(vertices,indices);
| |||
//--- create mesh
| |||
return(Create(dispatcher,buffer_scene,vertices,indices));
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Update vertices |
| |||
//+------------------------------------------------------------------+
| |||
bool VerticesSet(const DXVertex &vertices[])
| |||
{
| |||
//--- check size
| |||
if(ArraySize(vertices)<1)
| |||
return(false);
| |||
//--- create new vertex buffer
| |||
if(!m_buffer_vertex.Create(m_context,vertices))
| |||
{
| |||
Shutdown();
| |||
return(false);
| |||
}
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Update indices |
| |||
//+------------------------------------------------------------------+
| |||
bool IndicesSet(const uint &indices[])
| |||
{
| |||
//--- check size
| |||
if(ArraySize(indices)<1)
| |||
return(false);
| |||
//--- create new index buffer
| |||
if(!m_buffer_index.Create(m_context,indices))
| |||
{
| |||
Shutdown();
| |||
return(false);
| |||
}
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Update indices |
| |||
//+------------------------------------------------------------------+
| |||
bool TopologySet(ENUM_DX_PRIMITIVE_TOPOLOGY topology)
| |||
{
| |||
m_topology=topology;
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Get transform matrix |
| |||
//+------------------------------------------------------------------+
| |||
void TransformMatrixGet(DXMatrix &mat) const
| |||
{
| |||
mat=m_transform_matrix;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set transform matrix |
| |||
//+------------------------------------------------------------------+
| |||
void TransformMatrixSet(const DXMatrix &mat)
| |||
{
| |||
m_transform_matrix=mat;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Get diffuse color |
| |||
//+------------------------------------------------------------------+
| |||
void DiffuseColorGet(DXColor &clr) const
| |||
{
| |||
clr=m_diffuse_color;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set diffuse color |
| |||
//+------------------------------------------------------------------+
| |||
void DiffuseColorSet(const DXColor &clr)
| |||
{
| |||
m_diffuse_color=clr;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Get specular color |
| |||
//+------------------------------------------------------------------+
| |||
void SpecularColorGet(DXColor &clr) const
| |||
{
| |||
clr=m_specular_color;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set specular color |
| |||
//+------------------------------------------------------------------+
| |||
void SpecularColorSet(const DXColor &clr)
| |||
{
| |||
m_specular_color=clr;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Get specular power |
| |||
//+------------------------------------------------------------------+
| |||
void SpecularPowerGet(float &power) const
| |||
{
| |||
power=m_specular_power;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set specular power |
| |||
//+------------------------------------------------------------------+
| |||
void SpecularPowerSet(float power)
| |||
{
| |||
m_specular_power=power;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Get emission color |
| |||
//+------------------------------------------------------------------+
| |||
void EmissionColorGet(DXColor &clr) const
| |||
{
| |||
clr=m_emission_color;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set emission color |
| |||
//+------------------------------------------------------------------+
| |||
void EmissionColorSet(const DXColor &clr)
| |||
{
| |||
m_emission_color=clr;
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Render mesh |
| |||
//+------------------------------------------------------------------+
| |||
virtual bool Render(void) override
| |||
{
| |||
//--- update object buffer
| |||
DXInputObject input_data;
| |||
DXMatrixTranspose(input_data.transform,m_transform_matrix);
| |||
input_data.diffuse_color =m_diffuse_color;
| |||
input_data.emission_color=m_emission_color;
| |||
input_data.specular_color=m_specular_color;
| |||
input_data.specular_power=m_specular_power;
| |||
//--- clear shader textures
| |||
m_shader_pixel.TexturesClear();
| |||
//--- set buffers, shaders, topology and render
| |||
if(m_buffer_object.InputSet(input_data))
| |||
if(m_buffer_vertex.Render())
| |||
if(m_buffer_index.Render())
| |||
if(m_shader_vertex.InputSet(0,m_buffer_scene) && m_shader_vertex.InputSet(1,m_buffer_object))
| |||
if(m_shader_pixel.InputSet(0,m_buffer_scene) && m_shader_pixel.InputSet(1,m_buffer_object))
| |||
if(CheckPointer(m_texture)==POINTER_INVALID || m_shader_pixel.TextureSet(0,m_texture))
| |||
if(m_shader_vertex.Render())
| |||
if(m_shader_pixel.Render())
| |||
if(DXPrimiveTopologySet(m_context,m_topology))
| |||
return(DXDrawIndexed(m_context));
| |||
//---
| |||
return(false);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set texture from image file |
| |||
//+------------------------------------------------------------------+
| |||
bool TextureSet(CDXDispatcher &dispatcher,string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
| |||
{
| |||
//--- check if texture already exist
| |||
if(CheckPointer(m_texture)==POINTER_INVALID)
| |||
{
| |||
m_texture=dispatcher.TextureCreateFromFile(path,data_x,data_y,data_width,data_height);
| |||
if(m_texture==NULL)
| |||
return(false);
| |||
m_texture.AddRef();
| |||
return(true);
| |||
}
| |||
//--- update texture data
| |||
if(!m_texture.Create(m_context,path,data_x,data_y,data_width,data_height))
| |||
{
| |||
m_texture.Release();
| |||
m_texture=NULL;
| |||
return(false);
| |||
}
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Set texture from image data |
| |||
//+------------------------------------------------------------------+
| |||
bool TextureSet(CDXDispatcher &dispatcher,ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
| |||
{
| |||
//--- check if texture already exist
| |||
if(CheckPointer(m_texture)==POINTER_INVALID)
| |||
{
| |||
m_texture=dispatcher.TextureCreateFromData(format,width,height,data,data_x,data_y,data_width,data_height);
| |||
if(m_texture==NULL)
| |||
return(false);
| |||
m_texture.AddRef();
| |||
return(true);
| |||
}
| |||
//--- update texture data
| |||
if(!m_texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height))
| |||
{
| |||
m_texture.Release();
| |||
m_texture=NULL;
| |||
return(false);
| |||
}
| |||
//---
| |||
return(true);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Delete used texture |
| |||
//+------------------------------------------------------------------+
| |||
void TextureDelete()
| |||
{
| |||
//--- release texture
| |||
if(CheckPointer(m_texture)!=POINTER_INVALID)
| |||
{
| |||
m_texture.Release();
| |||
m_texture=NULL;
| |||
}
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Shutdown |
| |||
//+------------------------------------------------------------------+
| |||
virtual void Shutdown(void)
| |||
{
| |||
//--- release all dx resources
| |||
if(CheckPointer(m_buffer_vertex)!=POINTER_INVALID)
| |||
{
| |||
m_buffer_vertex.Release();
| |||
m_buffer_vertex=NULL;
| |||
}
| |||
if(CheckPointer(m_buffer_index)!=POINTER_INVALID)
| |||
{
| |||
m_buffer_index.Release();
| |||
m_buffer_index=NULL;
| |||
}
| |||
if(CheckPointer(m_buffer_object)!=POINTER_INVALID)
| |||
{
| |||
m_buffer_object.Release();
| |||
m_buffer_object=NULL;
| |||
}
| |||
if(CheckPointer(m_texture)!=POINTER_INVALID)
| |||
{
| |||
m_texture.Release();
| |||
m_texture=NULL;
| |||
}
| |||
if(CheckPointer(m_buffer_scene)!=POINTER_INVALID)
| |||
{
| |||
m_buffer_scene.Release();
| |||
m_buffer_scene=NULL;
| |||
}
| |||
if(CheckPointer(m_shader_pixel)!=POINTER_INVALID)
| |||
{
| |||
m_shader_pixel.Release();
| |||
m_shader_pixel=NULL;
| |||
}
| |||
if(CheckPointer(m_shader_vertex)!=POINTER_INVALID)
| |||
{
| |||
m_shader_vertex.Release();
| |||
m_shader_vertex=NULL;
| |||
}
| |||
m_topology =WRONG_VALUE;
| |||
}
| |||
};
| |||
//+------------------------------------------------------------------+
|