mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 19:49:19 +02:00
move vertex user data to a separate array
update vao creation to support optional vertex data
update mesh serialization to account for new user data location
change t3d spec: userdata:{float|uint|int} to userdata:bool
This commit is contained in:
121
Model3d.cpp
121
Model3d.cpp
@@ -209,7 +209,7 @@ inline void readMatrix(cParser &parser, float4x4 &matrix)
|
||||
parser >> matrix(x)[y];
|
||||
};
|
||||
|
||||
template <typename T> void UserdataParse(cParser &parser, gfx::basic_vertex &vertex)
|
||||
template <typename T> void UserdataParse(cParser &parser, gfx::vertex_userdata &vertex)
|
||||
{
|
||||
parser.getTokens(4);
|
||||
union
|
||||
@@ -220,7 +220,7 @@ template <typename T> void UserdataParse(cParser &parser, gfx::basic_vertex &ver
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
parser >> buf.InType;
|
||||
vertex.user_data[i] = buf.FloatType;
|
||||
vertex.data[i] = buf.FloatType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,27 +494,10 @@ std::pair<int, int> TSubModel::Load( cParser &parser, bool dynamic )
|
||||
if (eType < TP_ROTATOR)
|
||||
{ // wczytywanie wierzchołków
|
||||
token = parser.getToken<std::string>();
|
||||
enum class UserDataType
|
||||
{
|
||||
None,
|
||||
Float,
|
||||
Int,
|
||||
UInt,
|
||||
Count
|
||||
} user_data = UserDataType::None;
|
||||
bool has_userdata = false;
|
||||
if (token == "userdata:")
|
||||
{
|
||||
const static std::map<std::string, UserDataType> type_mapping{{"float", UserDataType::Float}, {"int", UserDataType::Int}, {"uint", UserDataType::UInt}};
|
||||
const std::string type = parser.getToken<std::string>();
|
||||
|
||||
if (auto it = type_mapping.find(type); it != type_mapping.end())
|
||||
{
|
||||
user_data = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
user_data = UserDataType::None;
|
||||
}
|
||||
has_userdata = parser.getToken<bool>();
|
||||
|
||||
token = parser.getToken<std::string>();
|
||||
}
|
||||
@@ -695,20 +678,19 @@ std::pair<int, int> TSubModel::Load( cParser &parser, bool dynamic )
|
||||
}
|
||||
}
|
||||
Vertices.resize( m_geometry.vertex_count ); // in case we had some degenerate triangles along the way
|
||||
gfx::calculate_indices( Indices, Vertices, transformscalestack );
|
||||
gfx::calculate_indices( Indices, Vertices, Userdata, transformscalestack );
|
||||
gfx::calculate_tangents( Vertices, Indices, GL_TRIANGLES );
|
||||
// update values potentially changed by indexing
|
||||
m_geometry.index_count = Indices.size();
|
||||
m_geometry.vertex_count = Vertices.size();
|
||||
}
|
||||
if (user_data != UserDataType::None)
|
||||
if (has_userdata)
|
||||
{
|
||||
const static std::array<void (*)(cParser &, gfx::basic_vertex &), static_cast<size_t>(UserDataType::Count)> parsers{nullptr, &UserdataParse<float>, &UserdataParse<int32_t>,
|
||||
&UserdataParse<uint32_t>};
|
||||
auto vertices { std::begin( Vertices ) };
|
||||
Userdata.resize(m_geometry.vertex_count);
|
||||
auto userdata { std::begin( Userdata ) };
|
||||
for( auto idx = 0; idx < m_geometry.vertex_count; ++idx ) {
|
||||
auto vertex { vertices + idx };
|
||||
parsers[static_cast<size_t>(user_data)](parser, *vertex);
|
||||
auto vertex { userdata + idx };
|
||||
UserdataParse<float>(parser, *vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1219,13 +1201,33 @@ void TSubModel::serialize_geometry( std::ostream &Output, bool const Packed, boo
|
||||
}
|
||||
if( m_geometry.handle != null_handle ) {
|
||||
if( Packed ) {
|
||||
for( auto const &vertex : GfxRenderer->Vertices( m_geometry.handle ) ) {
|
||||
vertex.serialize_packed( Output, Indexed, UserData );
|
||||
}
|
||||
auto vertices = GfxRenderer->Vertices( m_geometry.handle );
|
||||
auto userdatas = GfxRenderer->UserData( m_geometry.handle );
|
||||
bool has_userdata = !userdatas.empty();
|
||||
for( int i = 0; i < vertices.size(); ++i ) {
|
||||
vertices[i].serialize_packed( Output, Indexed );
|
||||
if (UserData)
|
||||
{
|
||||
if (has_userdata)
|
||||
userdatas[i].serialize_packed(Output);
|
||||
else
|
||||
gfx::vertex_userdata{}.serialize_packed( Output );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for( auto const &vertex : GfxRenderer->Vertices( m_geometry.handle ) ) {
|
||||
vertex.serialize( Output, Indexed, UserData );
|
||||
auto vertices = GfxRenderer->Vertices( m_geometry.handle );
|
||||
auto userdatas = GfxRenderer->UserData( m_geometry.handle );
|
||||
bool has_userdata = !userdatas.empty();
|
||||
for( int i = 0; i < vertices.size(); ++i ) {
|
||||
vertices[i].serialize( Output, Indexed );
|
||||
if (UserData)
|
||||
{
|
||||
if (has_userdata)
|
||||
userdatas[i].serialize(Output);
|
||||
else
|
||||
gfx::vertex_userdata{}.serialize( Output );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1306,7 +1308,7 @@ TSubModel::create_geometry( std::size_t &Indexoffset, std::size_t &Vertexoffset,
|
||||
eType < TP_ROTATOR ?
|
||||
eType :
|
||||
GL_POINTS );
|
||||
m_geometry.handle = GfxRenderer->Insert( Indices, Vertices, Bank, type );
|
||||
m_geometry.handle = GfxRenderer->Insert( Indices, Vertices, Userdata, Bank, type );
|
||||
}
|
||||
|
||||
if( m_geometry.handle != 0 ) {
|
||||
@@ -1705,6 +1707,7 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('E', '3', 'D', '0'));
|
||||
auto const e3d_spos = s.tellp();
|
||||
sn_utils::ls_uint32(s, 0);
|
||||
bool has_any_userdata = Root->HasAnyVertexUserData();
|
||||
|
||||
{
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('S', 'U', 'B', '0'));
|
||||
@@ -1731,20 +1734,26 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
|
||||
Root->serialize_indices( s, indexsize );
|
||||
|
||||
if (!(Global.iConvertModels & 8)) {
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '1' + 4 ) );
|
||||
int modeltype = 1;
|
||||
if(has_any_userdata) modeltype |= 4;
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '0' + modeltype ) );
|
||||
sn_utils::ls_uint32( s, 8 + m_vertexcount * 20 );
|
||||
Root->serialize_geometry( s, true, true, true );
|
||||
Root->serialize_geometry( s, true, true, has_any_userdata );
|
||||
}
|
||||
else {
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '2' + 4 ) );
|
||||
int modeltype = 2;
|
||||
if(has_any_userdata) modeltype |= 4;
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '0' + modeltype ) );
|
||||
sn_utils::ls_uint32( s, 8 + m_vertexcount * 48 );
|
||||
Root->serialize_geometry( s, false, true, true );
|
||||
Root->serialize_geometry( s, false, true, has_any_userdata );
|
||||
}
|
||||
}
|
||||
else {
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '0' + 4 ) );
|
||||
int modeltype = 0;
|
||||
if(has_any_userdata) modeltype |= 4;
|
||||
sn_utils::ls_uint32( s, MAKE_ID4( 'V', 'N', 'T', '0' + modeltype ) );
|
||||
sn_utils::ls_uint32( s, 8 + m_vertexcount * 32 );
|
||||
Root->serialize_geometry( s, false, false, true );
|
||||
Root->serialize_geometry( s, false, false, has_any_userdata );
|
||||
}
|
||||
|
||||
if (textures.size())
|
||||
@@ -1884,16 +1893,20 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
auto &submodel { Root[ submodeloffset.second ] };
|
||||
auto const &submodelgeometry { submodel.m_geometry };
|
||||
submodel.Vertices.resize( submodelgeometry.vertex_count );
|
||||
if(hasuserdata)
|
||||
submodel.Userdata.resize( submodelgeometry.vertex_count );
|
||||
m_vertexcount += submodelgeometry.vertex_count;
|
||||
switch( vertextype & 3 ) {
|
||||
case 0: {
|
||||
// legacy vnt0 format
|
||||
for( auto &vertex : submodel.Vertices ) {
|
||||
vertex.deserialize( s, hastangents, hasuserdata );
|
||||
for( int i = 0; i < submodel.Vertices.size(); ++i ) {
|
||||
submodel.Vertices[i].deserialize( s, hastangents );
|
||||
if(hasuserdata)
|
||||
submodel.Userdata[i].deserialize( s );
|
||||
if( submodel.eType < TP_ROTATOR ) {
|
||||
// normal vectors debug routine
|
||||
if( ( false == submodel.m_normalizenormals )
|
||||
&& ( std::abs( glm::length2( vertex.normal ) - 1.0f ) > 0.01f ) ) {
|
||||
&& ( std::abs( glm::length2( submodel.Vertices[i].normal ) - 1.0f ) > 0.01f ) ) {
|
||||
submodel.m_normalizenormals = TSubModel::normalize; // we don't know if uniform scaling would suffice
|
||||
WriteLog( "Bad model: non-unit normal vector(s) encountered during sub-model geometry deserialization", logtype::model );
|
||||
}
|
||||
@@ -1903,15 +1916,19 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
}
|
||||
case 1: {
|
||||
// expanded chunk formats
|
||||
for( auto &vertex : submodel.Vertices ) {
|
||||
vertex.deserialize_packed( s, hastangents, hasuserdata );
|
||||
for( int i = 0; i < submodel.Vertices.size(); ++i ) {
|
||||
submodel.Vertices[i].deserialize_packed( s, hastangents );
|
||||
if(hasuserdata)
|
||||
submodel.Userdata[i].deserialize_packed( s );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// expanded chunk formats
|
||||
for( auto &vertex : submodel.Vertices ) {
|
||||
vertex.deserialize( s, hastangents, hasuserdata );
|
||||
for( int i = 0; i < submodel.Vertices.size(); ++i ) {
|
||||
submodel.Vertices[i].deserialize( s, hastangents );
|
||||
if(hasuserdata)
|
||||
submodel.Userdata[i].deserialize( s );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2042,7 +2059,7 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
if( false == hastangents ) {
|
||||
gfx::calculate_tangents( Root[i].Vertices, Root[i].Indices, type );
|
||||
}
|
||||
Root[i].m_geometry.handle = GfxRenderer->Insert( Root[i].Indices, Root[i].Vertices, m_geometrybank, type );
|
||||
Root[i].m_geometry.handle = GfxRenderer->Insert( Root[i].Indices, Root[i].Vertices, Root[i].Userdata, m_geometrybank, type );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2181,6 +2198,14 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
normalize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TSubModel::HasAnyVertexUserData() const
|
||||
{
|
||||
for(const TSubModel* sm = this; sm; sm = sm->Next){
|
||||
if(!sm->Userdata.empty() || (sm->Child && sm->Child->HasAnyVertexUserData())) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
||||
|
||||
@@ -85,6 +85,8 @@ private:
|
||||
public: // chwilowo
|
||||
TAnimType b_Anim{ TAnimType::at_None };
|
||||
|
||||
bool HasAnyVertexUserData() const;
|
||||
|
||||
private:
|
||||
uint32_t iFlags{ 0x0200 }; // bit 9=1: submodel został utworzony a nie ustawiony na wczytany plik
|
||||
// flagi informacyjne:
|
||||
@@ -144,6 +146,7 @@ public: // chwilowo
|
||||
float3 v_TransVector { 0.0f, 0.0f, 0.0f };
|
||||
geometry_data m_geometry { /*this,*/ { 0, 0 }, 0, 0, 0, 0 };
|
||||
gfx::vertex_array Vertices;
|
||||
gfx::userdata_array Userdata;
|
||||
gfx::index_array Indices;
|
||||
float m_boundingradius { 0 };
|
||||
std::uintptr_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację
|
||||
|
||||
88
Track.cpp
88
Track.cpp
@@ -1140,6 +1140,7 @@ void TTrack::create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx
|
||||
{
|
||||
if (iCategoryFlag != 1)
|
||||
return; // only tracks for now
|
||||
gfx::userdata_array empty_userdata{};
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
@@ -1148,7 +1149,7 @@ void TTrack::create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx
|
||||
Segment->render_lines(vertices, 0.5f);
|
||||
|
||||
std::copy(vertices.begin(), vertices.end(), std::back_inserter(Bank));
|
||||
extra_map_geometry = GfxRenderer->Insert(vertices, Extra, GL_LINES);
|
||||
extra_map_geometry = GfxRenderer->Insert(vertices, empty_userdata, Extra, GL_LINES);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1157,12 +1158,12 @@ void TTrack::create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx
|
||||
|
||||
SwitchExtension->Segments[0]->render_lines(vertices, 0.5f);
|
||||
std::copy(vertices.begin(), vertices.end(), std::back_inserter(Bank));
|
||||
SwitchExtension->map_geometry[0] = GfxRenderer->Insert(vertices, Extra, GL_LINES);
|
||||
SwitchExtension->map_geometry[0] = GfxRenderer->Insert(vertices, empty_userdata, Extra, GL_LINES);
|
||||
|
||||
vertices.clear();
|
||||
SwitchExtension->Segments[1]->render_lines(vertices, 0.5f);
|
||||
std::copy(vertices.begin(), vertices.end(), std::back_inserter(Bank));
|
||||
SwitchExtension->map_geometry[1] = GfxRenderer->Insert(vertices, Extra, GL_LINES);
|
||||
SwitchExtension->map_geometry[1] = GfxRenderer->Insert(vertices, empty_userdata, Extra, GL_LINES);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1303,7 +1304,7 @@ glm::vec3 TTrack::get_nearest_point(const glm::dvec3 &point) const
|
||||
|
||||
// wypełnianie tablic VBO
|
||||
void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
|
||||
gfx::userdata_array empty_userdata;
|
||||
switch (iCategoryFlag & 15)
|
||||
{
|
||||
case 1: // tor
|
||||
@@ -1323,11 +1324,11 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
gfx::vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid > 0, texturelength);
|
||||
if( ( Bank != 0 ) && ( true == Geometry2.empty() ) ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
}
|
||||
if( ( Bank == 0 ) && ( false == Geometry2.empty() ) ) {
|
||||
// special variant, replace existing data for a turntable track
|
||||
GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry2[0], GL_TRIANGLE_STRIP);
|
||||
}
|
||||
}
|
||||
if (m_material1)
|
||||
@@ -1337,18 +1338,18 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
gfx::vertex_array vertices;
|
||||
if( ( Bank != 0 ) && ( true == Geometry1.empty() ) ) {
|
||||
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, texturelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear(); // reuse the scratchpad
|
||||
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, texturelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
}
|
||||
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
|
||||
// special variant, replace existing data for a turntable track
|
||||
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, texturelength );
|
||||
GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry1[0], GL_TRIANGLE_STRIP);
|
||||
vertices.clear(); // reuse the scratchpad
|
||||
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, texturelength );
|
||||
GfxRenderer->Replace( vertices, Geometry1[ 1 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry1[1], GL_TRIANGLE_STRIP);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1373,21 +1374,21 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { SwitchExtension->fOffset2, SwitchExtension->fOffset2 / 2 } );
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { SwitchExtension->fOffset2 / 2, 0.f } );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
if( jointlength > 0 ) {
|
||||
// part of the diverging rail touched by wheels of vehicle going straight
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, 0, jointlength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
// other rail, full length
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
if( m_material2 ) {
|
||||
@@ -1396,15 +1397,15 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -fMaxOffset + SwitchExtension->fOffset1, ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2 } );
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2, 0.f } );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// diverging rail, potentially minus part touched by wheels of vehicle going straight
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, jointlength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1417,22 +1418,22 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -SwitchExtension->fOffset2, -SwitchExtension->fOffset2 / 2 } );
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { -SwitchExtension->fOffset2 / 2, 0.f } );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// fixed parts
|
||||
// prawa szyna za iglicą
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
if( jointlength > 0 ) {
|
||||
// part of the diverging rail touched by wheels of vehicle going straight
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, 0, jointlength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
// other rail, full length
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength );
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
if( m_material2 ) {
|
||||
@@ -1441,16 +1442,16 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { fMaxOffset - SwitchExtension->fOffset1, ( fMaxOffset - SwitchExtension->fOffset1 ) / 2 } );
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { ( fMaxOffset - SwitchExtension->fOffset1 ) / 2, 0.f } );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// fixed parts
|
||||
// lewa szyna za iglicą
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
// diverging rail, potentially minus part touched by wheels of vehicle going straight
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, jointlength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1459,7 +1460,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
if( true == Global.CreateSwitchTrackbeds ) {
|
||||
gfx::vertex_array vertices;
|
||||
create_switch_trackbed( vertices );
|
||||
SwitchExtension->Geometry3 = GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP );
|
||||
SwitchExtension->Geometry3 = GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP);
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
@@ -1482,7 +1483,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
auto const texturelength { texture_length( m_material1 ) };
|
||||
gfx::vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid > 0, texturelength);
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
}
|
||||
if (m_material2)
|
||||
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
|
||||
@@ -1495,13 +1496,13 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
||||
// tylko jeśli jest z prawej
|
||||
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, texturelength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||
// tylko jeśli jest z lewej
|
||||
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, texturelength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1578,22 +1579,22 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 3 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 4 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 5 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1603,17 +1604,17 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render ); // z P2 do P4
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render ); // z P4 do P3=P1 (odwrócony)
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, true, texturelength, 1.0, 0, 0, {}, &b, render ); // z P1 do P2
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1668,7 +1669,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
cosa0 * u + sina0 * v + 0.5,
|
||||
-sina0 * u + cosa0 * v + 0.5 } );
|
||||
}
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_FAN ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_FAN));
|
||||
}
|
||||
break;
|
||||
} // tt_cross
|
||||
@@ -1687,7 +1688,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
{ // tworzenie trójkątów nawierzchni szosy
|
||||
gfx::vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid > 0, fTexLength);
|
||||
Geometry1.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry1.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
}
|
||||
if (m_material2)
|
||||
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
|
||||
@@ -1695,10 +1696,10 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
create_road_side_profile( rpts1, rpts2, bpts1 );
|
||||
gfx::vertex_array vertices;
|
||||
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, fTexLength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, fTexLength );
|
||||
Geometry2.emplace_back( GfxRenderer->Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
Geometry2.emplace_back(GfxRenderer->Insert(vertices, empty_userdata, Bank, GL_TRIANGLE_STRIP));
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1925,6 +1926,7 @@ void TTrack::RaAnimListAdd(TTrack *t)
|
||||
TTrack * TTrack::RaAnimate()
|
||||
{ // wykonanie rekurencyjne animacji, wywoływane przed wyświetleniem sektora
|
||||
// zwraca wskaźnik toru wymagającego dalszej animacji
|
||||
gfx::userdata_array empty_userdata;
|
||||
if( SwitchExtension->pNextAnim )
|
||||
SwitchExtension->pNextAnim = SwitchExtension->pNextAnim->RaAnimate();
|
||||
bool m = true; // animacja trwa
|
||||
@@ -1976,7 +1978,7 @@ TTrack * TTrack::RaAnimate()
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { SwitchExtension->fOffset2, SwitchExtension->fOffset2 / 2 } );
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { SwitchExtension->fOffset2 / 2, 0.f } );
|
||||
GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry1[0], GL_TRIANGLE_STRIP);
|
||||
vertices.clear();
|
||||
}
|
||||
if( m_material2 ) {
|
||||
@@ -1985,7 +1987,7 @@ TTrack * TTrack::RaAnimate()
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -fMaxOffset + SwitchExtension->fOffset1, ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2 } );
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2, 0.f } );
|
||||
GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry2[0], GL_TRIANGLE_STRIP);
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
@@ -1996,7 +1998,7 @@ TTrack * TTrack::RaAnimate()
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -SwitchExtension->fOffset2, -SwitchExtension->fOffset2 / 2 } );
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { -SwitchExtension->fOffset2 / 2, 0.f } );
|
||||
GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry1[0], GL_TRIANGLE_STRIP);
|
||||
vertices.clear();
|
||||
}
|
||||
if( m_material2 ) {
|
||||
@@ -2005,7 +2007,7 @@ TTrack * TTrack::RaAnimate()
|
||||
// composed from two parts: transition from blade to regular rail, and regular rail
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { fMaxOffset - SwitchExtension->fOffset1, ( fMaxOffset - SwitchExtension->fOffset1 ) / 2 } );
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { ( fMaxOffset - SwitchExtension->fOffset1 ) / 2, 0.f } );
|
||||
GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
|
||||
GfxRenderer->Replace(vertices, empty_userdata, Geometry2[0], GL_TRIANGLE_STRIP);
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +342,9 @@ TTraction::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
}
|
||||
|
||||
auto const elementcount = vertices.size() / 2;
|
||||
m_geometry = GfxRenderer->Insert( vertices, Bank, GL_LINES );
|
||||
|
||||
gfx::userdata_array empty_userdata{};
|
||||
m_geometry = GfxRenderer->Insert( vertices, empty_userdata, Bank, GL_LINES );
|
||||
|
||||
return elementcount;
|
||||
}
|
||||
|
||||
114
geometrybank.cpp
114
geometrybank.cpp
@@ -23,7 +23,6 @@ basic_vertex basic_vertex::convert(world_vertex const &world, glm::dvec3 const&
|
||||
vertex.position = static_cast<glm::vec3>(world.position - origin);
|
||||
vertex.normal = world.normal;
|
||||
vertex.texture = world.texture;
|
||||
vertex.user_data = world.user_data;
|
||||
return vertex;
|
||||
}
|
||||
|
||||
@@ -34,13 +33,12 @@ world_vertex basic_vertex::to_world(const glm::dvec3 &origin) const
|
||||
vertex.position = static_cast<glm::dvec3>(position) + origin;
|
||||
vertex.normal = normal;
|
||||
vertex.texture = texture;
|
||||
vertex.user_data = user_data;
|
||||
|
||||
return vertex;
|
||||
}
|
||||
|
||||
void
|
||||
basic_vertex::serialize( std::ostream &s, bool const Tangent, bool const UserData ) const {
|
||||
basic_vertex::serialize( std::ostream &s, bool const Tangent ) const {
|
||||
|
||||
sn_utils::s_vec3( s, position );
|
||||
sn_utils::s_vec3( s, normal );
|
||||
@@ -49,13 +47,10 @@ basic_vertex::serialize( std::ostream &s, bool const Tangent, bool const UserDat
|
||||
if( Tangent ) {
|
||||
sn_utils::s_vec4( s, tangent );
|
||||
}
|
||||
if( UserData ) {
|
||||
sn_utils::s_vec4( s, user_data );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
basic_vertex::deserialize( std::istream &s, bool const Tangent, bool const UserData ) {
|
||||
basic_vertex::deserialize( std::istream &s, bool const Tangent ) {
|
||||
|
||||
position = sn_utils::d_vec3( s );
|
||||
normal = sn_utils::d_vec3( s );
|
||||
@@ -64,13 +59,10 @@ basic_vertex::deserialize( std::istream &s, bool const Tangent, bool const UserD
|
||||
if( Tangent ) {
|
||||
tangent = sn_utils::d_vec4( s );
|
||||
}
|
||||
if( UserData ) {
|
||||
user_data = sn_utils::d_vec4( s );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
basic_vertex::serialize_packed( std::ostream &s, bool const Tangent, bool const UserData ) const {
|
||||
basic_vertex::serialize_packed( std::ostream &s, bool const Tangent ) const {
|
||||
|
||||
sn_utils::ls_uint64( s, glm::packHalf4x16( { position, 0.f } ) );
|
||||
sn_utils::ls_uint32( s, glm::packSnorm3x10_1x2( { normal, 0.f } ) );
|
||||
@@ -79,13 +71,10 @@ basic_vertex::serialize_packed( std::ostream &s, bool const Tangent, bool const
|
||||
if( Tangent ) {
|
||||
sn_utils::ls_uint32( s, glm::packSnorm3x10_1x2( tangent ) );
|
||||
}
|
||||
if( UserData ) {
|
||||
sn_utils::ls_uint64( s, glm::packHalf4x16( user_data ));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
basic_vertex::deserialize_packed( std::istream &s, bool const Tangent, bool const UserData ) {
|
||||
basic_vertex::deserialize_packed( std::istream &s, bool const Tangent ) {
|
||||
|
||||
position = glm::unpackHalf4x16( sn_utils::ld_uint64( s ) );
|
||||
normal = glm::unpackSnorm3x10_1x2( sn_utils::ld_uint32( s ) );
|
||||
@@ -94,9 +83,6 @@ basic_vertex::deserialize_packed( std::istream &s, bool const Tangent, bool cons
|
||||
if( Tangent ) {
|
||||
tangent = glm::unpackSnorm3x10_1x2( sn_utils::ld_uint32( s ) );
|
||||
}
|
||||
if( UserData ) {
|
||||
user_data = glm::unpackHalf4x16( sn_utils::ld_uint64( s ) );
|
||||
}
|
||||
}
|
||||
|
||||
// based on
|
||||
@@ -218,14 +204,18 @@ void calculate_tangents(vertex_array &vertices, index_array const &indices, int
|
||||
}
|
||||
}
|
||||
|
||||
void calculate_indices( index_array &Indices, vertex_array &Vertices, float tolerancescale ) {
|
||||
void calculate_indices( index_array &Indices, vertex_array &Vertices, userdata_array &Userdata, float tolerancescale ) {
|
||||
|
||||
Indices.resize( Vertices.size() );
|
||||
std::iota( std::begin( Indices ), std::end( Indices ), 0 );
|
||||
// gather instances of used vertices, replace the original vertex bank with it after you're done
|
||||
vertex_array indexedvertices;
|
||||
vertex_array indexedvertices{};
|
||||
userdata_array indexeduserdata{};
|
||||
indexedvertices.reserve( std::max<size_t>( 100, Vertices.size() / 3 ) ); // optimistic guesstimate, but should reduce re-allocation somewhat
|
||||
auto const matchtolerance { 1e-5f * tolerancescale };
|
||||
bool has_userdata = !Userdata.empty();
|
||||
if (has_userdata)
|
||||
indexeduserdata.reserve(std::max<size_t>(100, Userdata.size() / 3));
|
||||
auto const matchtolerance { 1e-5f * tolerancescale };
|
||||
for( auto idx = 0; idx < Indices.size(); ++idx ) {
|
||||
if( Indices[ idx ] < idx ) {
|
||||
// this index is pointing to a vertex out of linear order, i.e. it's an already processed duplicate we can skip
|
||||
@@ -235,31 +225,38 @@ void calculate_indices( index_array &Indices, vertex_array &Vertices, float tole
|
||||
Indices[ idx ] = indexedvertices.size();
|
||||
// see if there's any pointers in the remaining index subrange to similar enough vertices
|
||||
// if found, remap these to use our current vertex instead
|
||||
auto vertex { Vertices[ idx ] };
|
||||
const auto& vertex { Vertices[ idx ] };
|
||||
const auto* userdata{ has_userdata ? &Userdata[idx] : nullptr };
|
||||
auto matchiter { std::cbegin( Vertices ) + idx };
|
||||
auto matchuserdata = userdata;
|
||||
for( auto matchidx = idx + 1; matchidx < Indices.size() && matchidx < idx + Global.iConvertIndexRange; ++matchidx ) {
|
||||
++matchiter;
|
||||
++matchuserdata;
|
||||
if( ( glm::all( glm::epsilonEqual( vertex.position, matchiter->position, matchtolerance ) ) )
|
||||
&& ( glm::all( glm::epsilonEqual( vertex.normal, matchiter->normal, matchtolerance ) ) )
|
||||
&& ( glm::all( glm::epsilonEqual( vertex.texture, matchiter->texture, matchtolerance ) ) ) ) {
|
||||
&& ( glm::all( glm::epsilonEqual( vertex.texture, matchiter->texture, matchtolerance ) ) )
|
||||
&& ( !userdata || glm::all( glm::epsilonEqual( userdata->data, matchuserdata->data, matchtolerance ) ) ) ) {
|
||||
Indices[ matchidx ] = Indices[ idx ];
|
||||
}
|
||||
}
|
||||
indexedvertices.emplace_back( vertex );
|
||||
if(userdata)
|
||||
indexeduserdata.emplace_back( *userdata );
|
||||
}
|
||||
// done indexing, swap the source vertex bank with the processed one
|
||||
Vertices.swap( indexedvertices );
|
||||
Userdata.swap( indexeduserdata );
|
||||
}
|
||||
|
||||
// generic geometry bank class, allows storage, update and drawing of geometry chunks
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied data. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
geometry_bank::create( gfx::vertex_array &Vertices, unsigned int const Type ) {
|
||||
geometry_bank::create( gfx::vertex_array &Vertices, userdata_array &Userdata, unsigned int const Type ) {
|
||||
|
||||
if( true == Vertices.empty() ) { return { 0, 0 }; }
|
||||
if(Vertices.empty()) { return { 0, 0 }; }
|
||||
|
||||
m_chunks.emplace_back( Vertices, Type );
|
||||
m_chunks.emplace_back( Vertices, Userdata, Type );
|
||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||
gfx::geometry_handle chunkhandle { 0, static_cast<std::uint32_t>(m_chunks.size()) };
|
||||
// template method implementation
|
||||
@@ -270,11 +267,11 @@ geometry_bank::create( gfx::vertex_array &Vertices, unsigned int const Type ) {
|
||||
|
||||
// creates a new indexed geometry chunk of specified type from supplied data. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
geometry_bank::create( gfx::index_array &Indices, gfx::vertex_array &Vertices, unsigned int const Type ) {
|
||||
geometry_bank::create( gfx::index_array &Indices, gfx::vertex_array &Vertices, userdata_array &Userdata, unsigned int const Type ) {
|
||||
|
||||
if( true == Vertices.empty() ) { return { 0, 0 }; }
|
||||
if(Vertices.empty()) { return { 0, 0 }; }
|
||||
|
||||
m_chunks.emplace_back( Indices, Vertices, Type );
|
||||
m_chunks.emplace_back( Indices, Vertices, Userdata, Type );
|
||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||
gfx::geometry_handle chunkhandle { 0, static_cast<std::uint32_t>(m_chunks.size()) };
|
||||
// template method implementation
|
||||
@@ -285,7 +282,7 @@ geometry_bank::create( gfx::index_array &Indices, gfx::vertex_array &Vertices, u
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
geometry_bank::replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset ) {
|
||||
geometry_bank::replace( gfx::vertex_array &Vertices, userdata_array &Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset ) {
|
||||
|
||||
if( ( Geometry.chunk == 0 ) || ( Geometry.chunk > m_chunks.size() ) ) { return false; }
|
||||
|
||||
@@ -295,13 +292,16 @@ geometry_bank::replace( gfx::vertex_array &Vertices, gfx::geometry_handle const
|
||||
&& ( Vertices.size() == chunk.vertices.size() ) ) {
|
||||
// check first if we can get away with a simple swap...
|
||||
chunk.vertices.swap( Vertices );
|
||||
chunk.userdata.swap( Userdata );
|
||||
}
|
||||
else {
|
||||
// ...otherwise we need to do some legwork
|
||||
// NOTE: if the offset is larger than existing size of the chunk, it'll bridge the gap with 'blank' vertices
|
||||
// TBD: we could bail out with an error instead if such request occurs
|
||||
chunk.vertices.resize( Offset + Vertices.size(), gfx::basic_vertex() );
|
||||
chunk.userdata.resize( Offset + Userdata.size(), gfx::vertex_userdata() );
|
||||
chunk.vertices.insert( std::end( chunk.vertices ), std::begin( Vertices ), std::end( Vertices ) );
|
||||
chunk.userdata.insert( std::end( chunk.userdata ), std::begin( Userdata ), std::end( Userdata ) );
|
||||
}
|
||||
// template method implementation
|
||||
replace_( Geometry );
|
||||
@@ -311,11 +311,11 @@ geometry_bank::replace( gfx::vertex_array &Vertices, gfx::geometry_handle const
|
||||
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
geometry_bank::append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) {
|
||||
geometry_bank::append( gfx::vertex_array &Vertices, userdata_array &Userdata, gfx::geometry_handle const &Geometry ) {
|
||||
|
||||
if( ( Geometry.chunk == 0 ) || ( Geometry.chunk > m_chunks.size() ) ) { return false; }
|
||||
|
||||
return replace( Vertices, Geometry, gfx::geometry_bank::chunk( Geometry ).vertices.size() );
|
||||
return replace( Vertices, Userdata, Geometry, gfx::geometry_bank::chunk( Geometry ).vertices.size() );
|
||||
}
|
||||
|
||||
// draws geometry stored in specified chunk
|
||||
@@ -346,6 +346,13 @@ geometry_bank::vertices( gfx::geometry_handle const &Geometry ) const {
|
||||
return geometry_bank::chunk( Geometry ).vertices;
|
||||
}
|
||||
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
userdata_array const &
|
||||
geometry_bank::userdata( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
return geometry_bank::chunk( Geometry ).userdata;
|
||||
}
|
||||
|
||||
// geometry bank manager, holds collection of geometry banks
|
||||
|
||||
// performs a resource sweep
|
||||
@@ -366,9 +373,9 @@ geometrybank_manager::register_bank(std::unique_ptr<geometry_bank> bank) {
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
geometrybank_manager::create_chunk(vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) {
|
||||
geometrybank_manager::create_chunk(vertex_array &Vertices, userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type ) {
|
||||
|
||||
auto const newchunkhandle = bank( Geometry ).first->create( Vertices, Type );
|
||||
auto const newchunkhandle = bank( Geometry ).first->create( Vertices, Userdata, Type );
|
||||
|
||||
if( newchunkhandle.chunk != 0 ) { return { Geometry.bank, newchunkhandle.chunk }; }
|
||||
else { return { 0, 0 }; }
|
||||
@@ -376,9 +383,9 @@ geometrybank_manager::create_chunk(vertex_array &Vertices, gfx::geometrybank_han
|
||||
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
geometrybank_manager::create_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, unsigned int const Type ) {
|
||||
geometrybank_manager::create_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, unsigned int const Type ) {
|
||||
|
||||
auto const newchunkhandle = bank( Geometry ).first->create( Indices, Vertices, Type );
|
||||
auto const newchunkhandle = bank( Geometry ).first->create( Indices, Vertices, Userdata, Type );
|
||||
|
||||
if( newchunkhandle.chunk != 0 ) { return { Geometry.bank, newchunkhandle.chunk }; }
|
||||
else { return { 0, 0 }; }
|
||||
@@ -386,16 +393,16 @@ geometrybank_manager::create_chunk( gfx::index_array &Indices, gfx::vertex_array
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
geometrybank_manager::replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset ) {
|
||||
geometrybank_manager::replace( gfx::vertex_array &Vertices, userdata_array &Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset ) {
|
||||
|
||||
return bank( Geometry ).first->replace( Vertices, Geometry, Offset );
|
||||
return bank( Geometry ).first->replace( Vertices, Userdata, Geometry, Offset );
|
||||
}
|
||||
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
geometrybank_manager::append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) {
|
||||
geometrybank_manager::append( gfx::vertex_array &Vertices, userdata_array &Userdata, gfx::geometry_handle const &Geometry ) {
|
||||
|
||||
return bank( Geometry ).first->append( Vertices, Geometry );
|
||||
return bank( Geometry ).first->append( Vertices, Userdata, Geometry );
|
||||
}
|
||||
// draws geometry stored in specified chunk
|
||||
void
|
||||
@@ -423,4 +430,31 @@ geometrybank_manager::vertices( gfx::geometry_handle const &Geometry ) const {
|
||||
return bank( Geometry ).first->vertices( Geometry );
|
||||
}
|
||||
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
geometrybank_manager::userdata( gfx::geometry_handle const &Geometry ) const {
|
||||
|
||||
return bank( Geometry ).first->userdata( Geometry );
|
||||
}
|
||||
|
||||
void vertex_userdata::serialize(std::ostream &s) const
|
||||
{
|
||||
sn_utils::s_vec4(s, data);
|
||||
}
|
||||
|
||||
void vertex_userdata::deserialize(std::istream &s)
|
||||
{
|
||||
data = sn_utils::d_vec4(s);
|
||||
}
|
||||
|
||||
void vertex_userdata::serialize_packed(std::ostream &s) const
|
||||
{
|
||||
sn_utils::ls_uint64(s, glm::packHalf4x16(data));
|
||||
}
|
||||
|
||||
void vertex_userdata::deserialize_packed(std::istream &s)
|
||||
{
|
||||
data = glm::unpackHalf4x16(sn_utils::ld_uint64(s));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -21,7 +21,6 @@ struct basic_vertex {
|
||||
glm::vec3 normal; // 3d space
|
||||
glm::vec2 texture; // uv space
|
||||
glm::vec4 tangent; // xyz - tangent, w - handedness
|
||||
glm::vec4 user_data; // user data (for color or additional uv channels, not subject to post-processing)
|
||||
|
||||
basic_vertex() = default;
|
||||
basic_vertex( glm::vec3 Position, glm::vec3 Normal, glm::vec2 Texture ) :
|
||||
@@ -29,10 +28,18 @@ struct basic_vertex {
|
||||
{}
|
||||
static basic_vertex convert(world_vertex const &world, glm::dvec3 const &origin);
|
||||
world_vertex to_world(glm::dvec3 const &origin = glm::dvec3(0.)) const;
|
||||
void serialize( std::ostream&, bool const Tangent = false, bool const UserData = false ) const;
|
||||
void deserialize( std::istream&, bool const Tangent = false, bool const UserData = false );
|
||||
void serialize_packed( std::ostream&, bool const Tangent = false, bool const UserData = false ) const;
|
||||
void deserialize_packed( std::istream&, bool const Tangent = false, bool const UserData = false );
|
||||
void serialize( std::ostream&, bool const Tangent = false ) const;
|
||||
void deserialize( std::istream&, bool const Tangent = false );
|
||||
void serialize_packed( std::ostream&, bool const Tangent = false ) const;
|
||||
void deserialize_packed( std::istream&, bool const Tangent = false );
|
||||
};
|
||||
|
||||
struct vertex_userdata{
|
||||
glm::vec4 data; // user data (for color or additional uv channels, not subject to post-processing)
|
||||
void serialize( std::ostream& ) const;
|
||||
void deserialize( std::istream& );
|
||||
void serialize_packed( std::ostream& ) const;
|
||||
void deserialize_packed( std::istream& );
|
||||
};
|
||||
|
||||
// data streams carried in a vertex
|
||||
@@ -55,10 +62,11 @@ struct stream_units {
|
||||
using basic_index = std::uint32_t;
|
||||
|
||||
using vertex_array = std::vector<basic_vertex>;
|
||||
using userdata_array = std::vector<vertex_userdata>;
|
||||
using index_array = std::vector<basic_index>;
|
||||
|
||||
void calculate_tangents( vertex_array &vertices, index_array const &indices, int const type );
|
||||
void calculate_indices( index_array &Indices, vertex_array &Vertices, float tolerancescale = 1.0f );
|
||||
void calculate_indices( index_array &Indices, vertex_array &Vertices, userdata_array &Userdata, float tolerancescale = 1.0f );
|
||||
|
||||
// generic geometry bank class, allows storage, update and drawing of geometry chunks
|
||||
|
||||
@@ -102,13 +110,13 @@ public:
|
||||
|
||||
// methods:
|
||||
// creates a new geometry chunk of specified type from supplied data. returns: handle to the chunk or NULL
|
||||
auto create( gfx::vertex_array &Vertices, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
auto create( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
// creates a new indexed geometry chunk of specified type from supplied data. returns: handle to the chunk or NULL
|
||||
auto create( gfx::index_array &Indices, gfx::vertex_array &Vertices, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
auto create( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
// replaces vertex data of specified chunk with the supplied data, starting from specified offset
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
auto append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
auto append( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
// draws geometry stored in specified chunk
|
||||
auto draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) -> std::size_t;
|
||||
// draws geometry stored in supplied list of chunks
|
||||
@@ -122,8 +130,10 @@ public:
|
||||
void release();
|
||||
// provides direct access to index data of specfied chunk
|
||||
auto indices( gfx::geometry_handle const &Geometry ) const -> gfx::index_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &;
|
||||
|
||||
protected:
|
||||
// types:
|
||||
@@ -131,17 +141,20 @@ protected:
|
||||
unsigned int type; // kind of geometry used by the chunk
|
||||
gfx::vertex_array vertices; // geometry data
|
||||
gfx::index_array indices; // index data
|
||||
gfx::userdata_array userdata;
|
||||
// NOTE: constructor doesn't copy provided geometry data, but moves it
|
||||
geometry_chunk( gfx::vertex_array &Vertices, unsigned int Type ) :
|
||||
geometry_chunk( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, unsigned int Type ) :
|
||||
type( Type )
|
||||
{
|
||||
vertices.swap( Vertices );
|
||||
userdata.swap( Userdata );
|
||||
}
|
||||
// NOTE: constructor doesn't copy provided geometry data, but moves it
|
||||
geometry_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, unsigned int Type ) :
|
||||
geometry_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, unsigned int Type ) :
|
||||
type( Type )
|
||||
{
|
||||
vertices.swap( Vertices );
|
||||
userdata.swap( Userdata );
|
||||
indices.swap( Indices );
|
||||
}
|
||||
};
|
||||
@@ -186,13 +199,13 @@ public:
|
||||
// registers a new geometry bank. returns: handle to the bank
|
||||
auto register_bank(std::unique_ptr<geometry_bank> bank) -> gfx::geometrybank_handle;
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
auto create_chunk( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle;
|
||||
auto create_chunk( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle;
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
auto create_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
auto create_chunk( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, unsigned int const Type ) -> gfx::geometry_handle;
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
auto replace( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
auto append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
auto append( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry ) -> bool;
|
||||
// draws geometry stored in specified chunk
|
||||
void draw( gfx::geometry_handle const &Geometry, unsigned int const Streams = basic_streams );
|
||||
template <typename Iterator_>
|
||||
@@ -202,8 +215,10 @@ public:
|
||||
++First; } }
|
||||
// provides direct access to index data of specfied chunk
|
||||
auto indices( gfx::geometry_handle const &Geometry ) const -> gfx::index_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &;
|
||||
// sets target texture unit for the texture data stream
|
||||
auto units() -> gfx::stream_units & { return m_units; }
|
||||
// provides access to primitives count
|
||||
|
||||
@@ -66,28 +66,25 @@ public:
|
||||
gfx::geometrybank_handle
|
||||
Create_Bank() override { return m_geometry.register_bank(std::make_unique<null_geometrybank>()); }
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override { return m_geometry.create_chunk( Indices, Vertices, Geometry, Type ); }
|
||||
gfx::geometry_handle Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override {
|
||||
return m_geometry.create_chunk( Indices, Vertices, Userdata, Geometry, Type ); }
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override {
|
||||
gfx::geometry_handle Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override {
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.create_chunk(Vertices, Geometry, Type);
|
||||
return m_geometry.create_chunk(Vertices, Userdata, Geometry, Type);
|
||||
}
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) override {
|
||||
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override {
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.replace(Vertices, Geometry, Offset);
|
||||
return m_geometry.replace(Vertices, Userdata, Geometry, Offset);
|
||||
}
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) override {
|
||||
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override {
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.append(Vertices, Geometry);
|
||||
return m_geometry.append(Vertices, Userdata, Geometry);
|
||||
}
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const &
|
||||
@@ -95,6 +92,9 @@ public:
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::vertex_array const &
|
||||
Vertices( gfx::geometry_handle const &Geometry ) const override { return m_geometry.vertices(Geometry); }
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
UserData( gfx::geometry_handle const &Geometry ) const override { return m_geometry.userdata(Geometry); }
|
||||
// material methods
|
||||
material_handle
|
||||
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override {
|
||||
|
||||
@@ -53,6 +53,7 @@ void opengl33_vaogeometrybank::setup_buffer()
|
||||
vertexcount{ 0 },
|
||||
indexcount{ 0 };
|
||||
auto chunkiterator = m_chunks.cbegin();
|
||||
bool has_userdata{ false };
|
||||
for( auto &chunkrecord : m_chunkrecords ) {
|
||||
// fill records for all chunks, based on the chunk data
|
||||
chunkrecord.is_good = false; // if we're re-creating buffer, chunks might've been uploaded in the old one
|
||||
@@ -61,7 +62,9 @@ void opengl33_vaogeometrybank::setup_buffer()
|
||||
vertexcount += chunkrecord.vertex_count;
|
||||
chunkrecord.index_offset = indexcount;
|
||||
chunkrecord.index_count = chunkiterator->indices.size();
|
||||
chunkrecord.has_userdata = !chunkiterator->userdata.empty();
|
||||
indexcount += chunkrecord.index_count;
|
||||
has_userdata |= chunkrecord.has_userdata;
|
||||
++chunkiterator;
|
||||
}
|
||||
// the odds for all created chunks to get replaced with empty ones are quite low, but the possibility does exist
|
||||
@@ -89,13 +92,17 @@ void opengl33_vaogeometrybank::setup_buffer()
|
||||
m_vertexbuffer.emplace();
|
||||
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
|
||||
// TODO: allow to specify usage hint at the object creation, and pass it here
|
||||
m_vertexbuffer->allocate( gl::buffer::ARRAY_BUFFER, vertexcount * sizeof( gfx::basic_vertex ), GL_STATIC_DRAW );
|
||||
const int vertex_size = has_userdata ? sizeof( gfx::basic_vertex ) + sizeof(gfx::vertex_userdata) : sizeof(gfx::basic_vertex);
|
||||
m_vertexbuffer->allocate( gl::buffer::ARRAY_BUFFER, static_cast<int>(vertexcount * vertex_size), GL_STATIC_DRAW );
|
||||
if( ::glGetError() == GL_OUT_OF_MEMORY ) {
|
||||
ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" );
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
m_vertex_count = static_cast<int>(vertexcount);
|
||||
|
||||
setup_attrib();
|
||||
if(has_userdata)
|
||||
setup_userdata();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -106,9 +113,12 @@ opengl33_vaogeometrybank::setup_attrib(size_t offset)
|
||||
m_vao->setup_attrib( *m_vertexbuffer, 1, 3, GL_FLOAT, sizeof( basic_vertex ), offsetof(basic_vertex, normal) + offset * sizeof( basic_vertex ) );
|
||||
m_vao->setup_attrib( *m_vertexbuffer, 2, 2, GL_FLOAT, sizeof( basic_vertex ), offsetof(basic_vertex, texture) + offset * sizeof( basic_vertex ) );
|
||||
m_vao->setup_attrib( *m_vertexbuffer, 3, 4, GL_FLOAT, sizeof( basic_vertex ), offsetof(basic_vertex, tangent) + offset * sizeof( basic_vertex ) );
|
||||
m_vao->setup_attrib( *m_vertexbuffer, 4, 4, GL_FLOAT, sizeof( basic_vertex ), offsetof(basic_vertex, user_data) + offset * sizeof( basic_vertex ) );
|
||||
}
|
||||
|
||||
void opengl33_vaogeometrybank::setup_userdata(size_t offset) {
|
||||
const size_t offset_evaluated = m_vertex_count * sizeof(basic_vertex) + offset * sizeof( vertex_userdata );
|
||||
m_vao->setup_attrib( *m_vertexbuffer, 4, 4, GL_FLOAT, sizeof( vertex_userdata ), offsetof(vertex_userdata, data) + offset_evaluated );}
|
||||
|
||||
// draw() subclass details
|
||||
// NOTE: units and stream parameters are unused, but they're part of (legacy) interface
|
||||
// TBD: specialized bank/manager pair without the cruft?
|
||||
@@ -123,14 +133,18 @@ opengl33_vaogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stre
|
||||
return 0;
|
||||
|
||||
auto const &chunk = gfx::geometry_bank::chunk( Geometry );
|
||||
if( false == chunkrecord.is_good ) {
|
||||
if( !chunkrecord.is_good ) {
|
||||
m_vao->bind();
|
||||
// we may potentially need to upload new buffer data before we can draw it
|
||||
if( chunkrecord.index_count > 0 ) {
|
||||
m_indexbuffer->upload( gl::buffer::ELEMENT_ARRAY_BUFFER, chunk.indices.data(), chunkrecord.index_offset * sizeof( gfx::basic_index ), chunkrecord.index_count * sizeof( gfx::basic_index ) );
|
||||
}
|
||||
m_vertexbuffer->upload( gl::buffer::ARRAY_BUFFER, chunk.vertices.data(), chunkrecord.vertex_offset * sizeof( gfx::basic_vertex ), chunkrecord.vertex_count * sizeof( gfx::basic_vertex ) );
|
||||
chunkrecord.is_good = true;
|
||||
if(chunkrecord.has_userdata)
|
||||
m_vertexbuffer->upload(gl::buffer::ARRAY_BUFFER, chunk.userdata.data(),
|
||||
static_cast<int>(m_vertex_count * sizeof(gfx::basic_vertex) + chunkrecord.vertex_offset * sizeof(gfx::vertex_userdata)),
|
||||
static_cast<int>(chunkrecord.vertex_count * sizeof(gfx::vertex_userdata)));
|
||||
chunkrecord.is_good = true;
|
||||
}
|
||||
// render
|
||||
if( chunkrecord.index_count > 0 ) {
|
||||
|
||||
@@ -37,6 +37,7 @@ private:
|
||||
std::size_t vertex_count{ 0 }; // size of the chunk in the last established buffer
|
||||
std::size_t index_offset{ 0 };
|
||||
std::size_t index_count{ 0 };
|
||||
bool has_userdata{ false };
|
||||
bool is_good{ false }; // true if local content of the chunk matches the data on the opengl end
|
||||
};
|
||||
|
||||
@@ -59,6 +60,8 @@ private:
|
||||
setup_buffer();
|
||||
void
|
||||
setup_attrib(size_t offset = 0);
|
||||
void
|
||||
setup_userdata(size_t offset = 0);
|
||||
void
|
||||
delete_buffer();
|
||||
|
||||
@@ -67,6 +70,7 @@ private:
|
||||
std::optional<gl::buffer> m_indexbuffer; // index buffer data on the opengl end
|
||||
std::optional<gl::vao> m_vao;
|
||||
chunkrecord_sequence m_chunkrecords; // helper data for all stored geometry chunks, in matching order
|
||||
int m_vertex_count;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -111,7 +111,8 @@ bool opengl33_renderer::Init(GLFWwindow *Window)
|
||||
|
||||
gfx::vertex_array billboard_array{
|
||||
{{-size, size, 0.f}, glm::vec3(), {1.f, 1.f}}, {{size, size, 0.f}, glm::vec3(), {0.f, 1.f}}, {{-size, -size, 0.f}, glm::vec3(), {1.f, 0.f}}, {{size, -size, 0.f}, glm::vec3(), {0.f, 0.f}}};
|
||||
m_billboardgeometry = m_geometry.create_chunk(billboard_array, geometrybank, GL_TRIANGLE_STRIP);
|
||||
gfx::userdata_array userdata{};
|
||||
m_billboardgeometry = m_geometry.create_chunk(billboard_array, userdata, geometrybank, GL_TRIANGLE_STRIP);
|
||||
m_empty_vao = std::make_unique<gl::vao>();
|
||||
|
||||
try
|
||||
@@ -1961,34 +1962,34 @@ gfx::geometrybank_handle opengl33_renderer::Create_Bank()
|
||||
}
|
||||
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle opengl33_renderer::Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type )
|
||||
gfx::geometry_handle opengl33_renderer::Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type)
|
||||
{
|
||||
// NOTE: we expect indexed geometry to come with calculated tangents
|
||||
return m_geometry.create_chunk( Indices, Vertices, Geometry, Type );
|
||||
return m_geometry.create_chunk( Indices, Vertices, Userdata, Geometry, Type );
|
||||
}
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle opengl33_renderer::Insert(gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type)
|
||||
gfx::geometry_handle opengl33_renderer::Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type)
|
||||
{
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.create_chunk(Vertices, Geometry, Type);
|
||||
return m_geometry.create_chunk(Vertices, Userdata, Geometry, Type);
|
||||
}
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool opengl33_renderer::Replace(gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset)
|
||||
bool opengl33_renderer::Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset)
|
||||
{
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.replace(Vertices, Geometry, Offset);
|
||||
return m_geometry.replace(Vertices, Userdata, Geometry, Offset);
|
||||
}
|
||||
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool opengl33_renderer::Append(gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type)
|
||||
bool opengl33_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type)
|
||||
{
|
||||
gfx::calculate_tangents(Vertices, gfx::index_array(), Type);
|
||||
|
||||
return m_geometry.append(Vertices, Geometry);
|
||||
return m_geometry.append(Vertices, Userdata, Geometry);
|
||||
}
|
||||
|
||||
// provides direct access to index data of specfied chunk
|
||||
@@ -2003,6 +2004,11 @@ gfx::vertex_array const &opengl33_renderer::Vertices(gfx::geometry_handle const
|
||||
return m_geometry.vertices(Geometry);
|
||||
}
|
||||
|
||||
gfx::userdata_array const &opengl33_renderer::UserData(const gfx::geometry_handle &Geometry) const
|
||||
{
|
||||
return m_geometry.userdata(Geometry);
|
||||
}
|
||||
|
||||
// material methods
|
||||
material_handle opengl33_renderer::Fetch_Material(std::string const &Filename, bool const Loadnow)
|
||||
{
|
||||
@@ -4829,3 +4835,4 @@ std::unique_ptr<gfx_renderer> opengl33_renderer::create_func()
|
||||
}
|
||||
|
||||
bool opengl33_renderer::renderer_register = gfx_renderer_factory::get_instance()->register_backend("modern", opengl33_renderer::create_func);
|
||||
|
||||
|
||||
@@ -58,23 +58,22 @@ class opengl33_renderer : public gfx_renderer {
|
||||
gfx::geometrybank_handle
|
||||
Create_Bank() override;
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
|
||||
gfx::geometry_handle Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
|
||||
gfx::geometry_handle Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) override;
|
||||
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) override;
|
||||
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override;
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const &
|
||||
Indices( gfx::geometry_handle const &Geometry ) const override;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::vertex_array const &
|
||||
Vertices( gfx::geometry_handle const &Geometry ) const override;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
UserData( gfx::geometry_handle const &Geometry ) const override;
|
||||
// material methods
|
||||
material_handle
|
||||
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
|
||||
|
||||
@@ -306,7 +306,8 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
{ { size, size, 0.f }, glm::vec3(), { 0.f, 1.f } },
|
||||
{ { -size, -size, 0.f }, glm::vec3(), { 1.f, 0.f } },
|
||||
{ { size, -size, 0.f }, glm::vec3(), { 0.f, 0.f } } };
|
||||
m_billboardgeometry = m_geometry.create_chunk(billboard_array, geometrybank, GL_TRIANGLE_STRIP);
|
||||
gfx::userdata_array userdata{};
|
||||
m_billboardgeometry = m_geometry.create_chunk(billboard_array, userdata, geometrybank, GL_TRIANGLE_STRIP);
|
||||
// prepare debug mode objects
|
||||
//m_quadric = ::gluNewQuadric();
|
||||
//::gluQuadricNormals( m_quadric, GLU_FLAT );
|
||||
@@ -1689,31 +1690,31 @@ opengl_renderer::Create_Bank() {
|
||||
}
|
||||
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
opengl_renderer::Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) {
|
||||
gfx::geometry_handle opengl_renderer::Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type)
|
||||
{
|
||||
|
||||
return m_geometry.create_chunk( Indices, Vertices, Geometry, Type );
|
||||
return m_geometry.create_chunk( Indices, Vertices, Userdata, Geometry, Type );
|
||||
}
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
opengl_renderer::Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) {
|
||||
gfx::geometry_handle opengl_renderer::Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type)
|
||||
{
|
||||
|
||||
return m_geometry.create_chunk( Vertices, Geometry, Type );
|
||||
return m_geometry.create_chunk( Vertices, Userdata, Geometry, Type );
|
||||
}
|
||||
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
opengl_renderer::Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset ) {
|
||||
bool opengl_renderer::Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset)
|
||||
{
|
||||
|
||||
return m_geometry.replace( Vertices, Geometry, Offset );
|
||||
return m_geometry.replace( Vertices, Userdata, Geometry, Offset );
|
||||
}
|
||||
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
opengl_renderer::Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) {
|
||||
bool opengl_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type)
|
||||
{
|
||||
|
||||
return m_geometry.append( Vertices, Geometry );
|
||||
return m_geometry.append( Vertices, Userdata, Geometry );
|
||||
}
|
||||
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
@@ -1730,6 +1731,11 @@ opengl_renderer::Vertices( gfx::geometry_handle const &Geometry ) const {
|
||||
return m_geometry.vertices( Geometry );
|
||||
}
|
||||
|
||||
gfx::userdata_array const &opengl_renderer::UserData(const gfx::geometry_handle &Geometry) const
|
||||
{
|
||||
return m_geometry.userdata( Geometry );
|
||||
}
|
||||
|
||||
// material methods
|
||||
material_handle
|
||||
opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow ) {
|
||||
@@ -4510,3 +4516,4 @@ std::unique_ptr<gfx_renderer> opengl_renderer::create_func()
|
||||
}
|
||||
|
||||
bool opengl_renderer::renderer_register = gfx_renderer_factory::get_instance()->register_backend("legacy", opengl_renderer::create_func);
|
||||
|
||||
|
||||
@@ -58,23 +58,22 @@ public:
|
||||
gfx::geometrybank_handle
|
||||
Create_Bank() override;
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
|
||||
gfx::geometry_handle Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
gfx::geometry_handle
|
||||
Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
|
||||
gfx::geometry_handle Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) override;
|
||||
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
bool
|
||||
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) override;
|
||||
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override;
|
||||
// provides direct access to index data of specfied chunk
|
||||
gfx::index_array const &
|
||||
Indices( gfx::geometry_handle const &Geometry ) const override;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::vertex_array const &
|
||||
Vertices( gfx::geometry_handle const &Geometry ) const override;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
gfx::userdata_array const &
|
||||
UserData( gfx::geometry_handle const &Geometry ) const override;
|
||||
// material methods
|
||||
material_handle
|
||||
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
|
||||
|
||||
14
renderer.h
14
renderer.h
@@ -35,17 +35,19 @@ public:
|
||||
// creates a new geometry bank. returns: handle to the bank or NULL
|
||||
virtual auto Create_Bank() -> gfx::geometrybank_handle = 0;
|
||||
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
virtual auto Insert( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle = 0;
|
||||
virtual auto Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) -> gfx::geometry_handle = 0;
|
||||
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
||||
virtual auto Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle = 0;
|
||||
virtual auto Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) -> gfx::geometry_handle = 0;
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
virtual auto Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) -> bool = 0;
|
||||
virtual auto Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) -> bool = 0;
|
||||
// adds supplied vertex data at the end of specified chunk
|
||||
virtual auto Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) -> bool = 0;
|
||||
virtual auto Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) -> bool = 0;
|
||||
// provides direct access to index data of specfied chunk
|
||||
virtual auto Indices( gfx::geometry_handle const &Geometry ) const->gfx::index_array const & = 0;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0;
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0;
|
||||
// provides direct access to vertex user data of specfied chunk
|
||||
virtual auto UserData( gfx::geometry_handle const &Geometry ) const ->gfx::userdata_array const & = 0;
|
||||
// material methods
|
||||
virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0;
|
||||
virtual void Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) = 0;
|
||||
|
||||
@@ -962,10 +962,11 @@ basic_section::create_geometry() {
|
||||
void basic_section::create_map_geometry(const gfx::geometrybank_handle handle)
|
||||
{
|
||||
std::vector<gfx::basic_vertex> lines;
|
||||
gfx::userdata_array userdata{};
|
||||
for (auto &cell : m_cells)
|
||||
cell.create_map_geometry(lines, handle);
|
||||
|
||||
m_map_geometryhandle = GfxRenderer->Insert(lines, handle, GL_LINES);
|
||||
m_map_geometryhandle = GfxRenderer->Insert(lines, userdata, handle, GL_LINES);
|
||||
}
|
||||
|
||||
void basic_section::get_map_active_paths(map_colored_paths &handles)
|
||||
@@ -1726,15 +1727,16 @@ void basic_region::create_map_geometry()
|
||||
void basic_region::update_poi_geometry()
|
||||
{
|
||||
std::vector<gfx::basic_vertex> vertices;
|
||||
gfx::userdata_array userdata;
|
||||
for (const auto sem : map::Objects.entries)
|
||||
vertices.push_back(std::move(sem->vertex()));
|
||||
|
||||
if (!m_map_poipoints) {
|
||||
gfx::geometrybank_handle poibank = GfxRenderer->Create_Bank();
|
||||
m_map_poipoints = GfxRenderer->Insert(vertices, poibank, GL_POINTS);
|
||||
m_map_poipoints = GfxRenderer->Insert(vertices, userdata, poibank, GL_POINTS);
|
||||
}
|
||||
else {
|
||||
GfxRenderer->Replace(vertices, m_map_poipoints, GL_POINTS);
|
||||
GfxRenderer->Replace(vertices, userdata, m_map_poipoints, GL_POINTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,12 +62,14 @@ void
|
||||
shape_node::shapenode_data::serialize( std::ostream &Output ) const {
|
||||
// bounding area
|
||||
area.serialize( Output );
|
||||
bool has_userdata = !userdata.empty();
|
||||
// visibility
|
||||
sn_utils::ls_float64( Output, rangesquared_min );
|
||||
sn_utils::ls_float64( Output, rangesquared_max );
|
||||
sn_utils::s_bool( Output, visible );
|
||||
// material
|
||||
sn_utils::s_bool( Output, translucent );
|
||||
sn_utils::s_bool( Output, has_userdata );
|
||||
// NOTE: material handle is created dynamically on load
|
||||
sn_utils::s_str(
|
||||
Output,
|
||||
@@ -80,9 +82,12 @@ shape_node::shapenode_data::serialize( std::ostream &Output ) const {
|
||||
// NOTE: geometry handle is created dynamically on load
|
||||
// vertex count, followed by vertex data
|
||||
sn_utils::ls_uint32( Output, vertices.size() );
|
||||
for( auto const &vertex : vertices ) {
|
||||
gfx::basic_vertex::convert(vertex, origin)
|
||||
.serialize( Output, false, true );
|
||||
for( int i = 0; i < vertices.size(); ++i ) {
|
||||
gfx::basic_vertex::convert(vertices[i], origin)
|
||||
.serialize( Output, false );
|
||||
if(has_userdata){
|
||||
userdata[i].serialize(Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +102,7 @@ shape_node::shapenode_data::deserialize( std::istream &Input ) {
|
||||
visible = sn_utils::d_bool( Input );
|
||||
// material
|
||||
translucent = sn_utils::d_bool( Input );
|
||||
bool has_userdata = sn_utils::d_bool( Input );
|
||||
auto const materialname { sn_utils::d_str( Input ) };
|
||||
if( false == materialname.empty() ) {
|
||||
material = GfxRenderer->Fetch_Material( materialname );
|
||||
@@ -107,10 +113,14 @@ shape_node::shapenode_data::deserialize( std::istream &Input ) {
|
||||
// NOTE: geometry handle is acquired during geometry creation
|
||||
// vertex data
|
||||
vertices.resize( sn_utils::ld_uint32( Input ) );
|
||||
if(has_userdata)
|
||||
userdata.resize(vertices.size());
|
||||
gfx::basic_vertex localvertex;
|
||||
for( auto &vertex : vertices ) {
|
||||
localvertex.deserialize( Input, false, true );
|
||||
vertex = localvertex.to_world(origin);
|
||||
for( int i = 0; i < vertices.size(); ++i ) {
|
||||
localvertex.deserialize( Input, false );
|
||||
vertices[i] = localvertex.to_world(origin);
|
||||
if(has_userdata)
|
||||
userdata[i].deserialize( Input );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,24 +357,40 @@ shape_node::convert( TSubModel const *Submodel ) {
|
||||
|
||||
int vertexcount { 0 };
|
||||
std::vector<world_vertex> importedvertices;
|
||||
world_vertex vertex, vertex1, vertex2;
|
||||
gfx::userdata_array importeduserdata;
|
||||
if(!GfxRenderer->Indices(Submodel->m_geometry.handle).empty()){
|
||||
const auto& vertices = GfxRenderer->Vertices(Submodel->m_geometry.handle);
|
||||
const auto& userdatas = GfxRenderer->UserData(Submodel->m_geometry.handle);
|
||||
bool has_userdata = !userdatas.empty();
|
||||
world_vertex vertex;
|
||||
for(const auto index : GfxRenderer->Indices(Submodel->m_geometry.handle)){
|
||||
vertex = vertices[index].to_world();
|
||||
importedvertices.emplace_back(vertex);
|
||||
if (has_userdata)
|
||||
importeduserdata.emplace_back(userdatas[index]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
for( auto const &sourcevertex : GfxRenderer->Vertices( Submodel->m_geometry.handle ) ) {
|
||||
vertex = sourcevertex.to_world();
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||
world_vertex vertex, vertex1, vertex2;
|
||||
gfx::vertex_userdata userdata, userdata1, userdata2;
|
||||
const auto& vertices = GfxRenderer->Vertices(Submodel->m_geometry.handle);
|
||||
const auto& userdatas = GfxRenderer->UserData(Submodel->m_geometry.handle);
|
||||
bool has_userdata = !userdatas.empty();
|
||||
for( int i = 0; i < vertices.size(); ++i ) {
|
||||
vertex = vertices[i].to_world();
|
||||
if( has_userdata ) userdata = userdatas[i];
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; userdata1 = userdata; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; userdata2 = userdata; }
|
||||
else if( vertexcount >= 2 ) {
|
||||
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||
if( !degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex2 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
if( has_userdata ) {
|
||||
importeduserdata.emplace_back( userdata1 );
|
||||
importeduserdata.emplace_back( userdata2 );
|
||||
importeduserdata.emplace_back( userdata );
|
||||
}
|
||||
}
|
||||
// start a new triangle
|
||||
vertexcount = -1;
|
||||
@@ -377,6 +403,7 @@ shape_node::convert( TSubModel const *Submodel ) {
|
||||
|
||||
// assign imported geometry to the node...
|
||||
m_data.vertices.swap( importedvertices );
|
||||
m_data.userdata.swap( importeduserdata );
|
||||
// ...and calculate center...
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
m_data.area.center += vertex.position;
|
||||
@@ -427,7 +454,7 @@ shape_node::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
vertices.emplace_back(gfx::basic_vertex::convert(vertex, m_data.origin));
|
||||
}
|
||||
m_data.geometry = GfxRenderer->Insert( vertices, Bank, GL_TRIANGLES );
|
||||
m_data.geometry = GfxRenderer->Insert(vertices, m_data.userdata, Bank, GL_TRIANGLES);
|
||||
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
|
||||
}
|
||||
|
||||
@@ -656,7 +683,7 @@ lines_node::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
vertex.normal,
|
||||
vertex.texture );
|
||||
}
|
||||
m_data.geometry = GfxRenderer->Insert( vertices, Bank, GL_LINES );
|
||||
m_data.geometry = GfxRenderer->Insert( vertices, m_data.userdata, Bank, GL_LINES );
|
||||
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
glm::dvec3 origin; // world position of the relative coordinate system origin
|
||||
gfx::geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
|
||||
std::vector<world_vertex> vertices; // world space source data of the geometry
|
||||
gfx::userdata_array userdata;
|
||||
// methods:
|
||||
// sends content of the struct to provided stream
|
||||
void
|
||||
@@ -192,6 +193,7 @@ public:
|
||||
glm::dvec3 origin; // world position of the relative coordinate system origin
|
||||
gfx::geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
|
||||
std::vector<world_vertex> vertices; // world space source data of the geometry
|
||||
gfx::userdata_array userdata;
|
||||
// methods:
|
||||
// sends content of the struct to provided stream
|
||||
void
|
||||
|
||||
@@ -621,7 +621,8 @@ void ui::obstacle_insert_window::render_content()
|
||||
|
||||
std::vector<gfx::basic_vertex> vertices;
|
||||
vertices.emplace_back(std::move(obstacle->vertex()));
|
||||
GfxRenderer->Append(vertices, simulation::Region->get_map_poi_geometry(), GL_POINTS);
|
||||
gfx::userdata_array userdata{};
|
||||
GfxRenderer->Append(vertices, userdata, simulation::Region->get_map_poi_geometry(), GL_POINTS);
|
||||
|
||||
map::Objects.entries.push_back(std::move(obstacle));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user