mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-21 01:19:18 +02:00
continued refactoring: lines, terrain models; render culling optimizations and fixes
This commit is contained in:
206
scenenode.cpp
206
scenenode.cpp
@@ -207,6 +207,65 @@ shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// imports data from provided submodel
|
||||
shape_node &
|
||||
shape_node::convert( TSubModel const *Submodel ) {
|
||||
|
||||
m_name = Submodel->pName;
|
||||
m_data.lighting.ambient = Submodel->f4Ambient;
|
||||
m_data.lighting.diffuse = Submodel->f4Diffuse;
|
||||
m_data.lighting.specular = Submodel->f4Specular;
|
||||
m_data.material = Submodel->m_material;
|
||||
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).has_alpha );
|
||||
// NOTE: we set unlimited view range typical for terrain, because we don't expect to convert any other 3d models
|
||||
m_data.rangesquared_max = std::numeric_limits<double>::max();
|
||||
|
||||
if( Submodel->m_geometry == null_handle ) { return *this; }
|
||||
|
||||
int vertexcount { 0 };
|
||||
std::vector<world_vertex> importedvertices;
|
||||
world_vertex vertex, vertex1, vertex2;
|
||||
for( auto const &sourcevertex : GfxRenderer.Vertices( Submodel->m_geometry ) ) {
|
||||
vertex.position = sourcevertex.position;
|
||||
vertex.normal = sourcevertex.normal;
|
||||
vertex.texture = sourcevertex.texture;
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||
else if( vertexcount >= 2 ) {
|
||||
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex2 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
}
|
||||
// start a new triangle
|
||||
vertexcount = -1;
|
||||
}
|
||||
++vertexcount;
|
||||
}
|
||||
|
||||
if( true == importedvertices.empty() ) { return *this; }
|
||||
|
||||
// assign imported geometry to the node...
|
||||
m_data.vertices.swap( importedvertices );
|
||||
// ...and calculate center...
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
m_data.area.center += vertex.position;
|
||||
}
|
||||
m_data.area.center /= m_data.vertices.size();
|
||||
// ...and bounding area
|
||||
double squareradius { 0.0 };
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
squareradius = std::max(
|
||||
squareradius,
|
||||
glm::length2( vertex.position - m_data.area.center ) );
|
||||
}
|
||||
m_data.area.radius = std::max<float>(
|
||||
m_data.area.radius,
|
||||
std::sqrt( squareradius ) );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||
bool
|
||||
shape_node::merge( shape_node &Shape ) {
|
||||
@@ -260,6 +319,151 @@ shape_node::compute_radius() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// restores content of the node from provded input stream
|
||||
lines_node &
|
||||
lines_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||
|
||||
// import common data
|
||||
m_name = Nodedata.name;
|
||||
m_data.rangesquared_min = Nodedata.range_min * Nodedata.range_min;
|
||||
m_data.rangesquared_max = (
|
||||
Nodedata.range_max >= 0.0 ?
|
||||
Nodedata.range_max * Nodedata.range_max :
|
||||
std::numeric_limits<double>::max() );
|
||||
|
||||
// material
|
||||
Input.getTokens( 3, false );
|
||||
Input
|
||||
>> m_data.lighting.diffuse.r
|
||||
>> m_data.lighting.diffuse.g
|
||||
>> m_data.lighting.diffuse.b;
|
||||
m_data.lighting.diffuse /= 255.f;
|
||||
m_data.lighting.diffuse.a = 1.f;
|
||||
Input.getTokens( 1, false );
|
||||
Input
|
||||
>> m_data.line_width;
|
||||
m_data.line_width = std::min( 30.f, m_data.line_width ); // 30 pix equals rougly width of a signal pole viewed from ~1m away
|
||||
|
||||
// geometry
|
||||
enum subtype {
|
||||
lines,
|
||||
line_strip,
|
||||
line_loop
|
||||
} const nodetype = (
|
||||
Nodedata.type == "lines" ? lines :
|
||||
Nodedata.type == "line_strip" ? line_strip :
|
||||
line_loop );
|
||||
std::size_t vertexcount { 0 };
|
||||
world_vertex vertex, vertex0, vertex1;
|
||||
std::string token = Input.getToken<std::string>();
|
||||
do {
|
||||
vertex.position.x = std::atof( token.c_str() );
|
||||
Input.getTokens( 2, false );
|
||||
Input
|
||||
>> vertex.position.y
|
||||
>> vertex.position.z;
|
||||
// convert all data to gl_lines to allow data merge for matching nodes
|
||||
switch( nodetype ) {
|
||||
case lines: {
|
||||
m_data.vertices.emplace_back( vertex );
|
||||
break;
|
||||
}
|
||||
case line_strip: {
|
||||
if( vertexcount > 0 ) {
|
||||
m_data.vertices.emplace_back( vertex1 );
|
||||
m_data.vertices.emplace_back( vertex );
|
||||
}
|
||||
vertex1 = vertex;
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
case line_loop: {
|
||||
if( vertexcount == 0 ) {
|
||||
vertex0 = vertex;
|
||||
vertex1 = vertex;
|
||||
}
|
||||
else {
|
||||
m_data.vertices.emplace_back( vertex1 );
|
||||
m_data.vertices.emplace_back( vertex );
|
||||
}
|
||||
vertex1 = vertex;
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
token = Input.getToken<std::string>();
|
||||
|
||||
} while( token != "endline" );
|
||||
// add closing line for the loop
|
||||
if( ( nodetype == line_loop )
|
||||
&& ( vertexcount > 2 ) ) {
|
||||
m_data.vertices.emplace_back( vertex1 );
|
||||
m_data.vertices.emplace_back( vertex0 );
|
||||
}
|
||||
if( m_data.vertices.size() % 2 != 0 ) {
|
||||
ErrorLog( "Lines node specified odd number of vertices, encountered in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
|
||||
m_data.vertices.pop_back();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||
bool
|
||||
lines_node::merge( lines_node &Lines ) {
|
||||
|
||||
if( ( m_data.line_width != Lines.m_data.line_width )
|
||||
|| ( m_data.lighting != Lines.m_data.lighting ) ) {
|
||||
// can't merge nodes with different appearance
|
||||
return false;
|
||||
}
|
||||
// add geometry from provided node
|
||||
m_data.area.center =
|
||||
interpolate(
|
||||
m_data.area.center, Lines.m_data.area.center,
|
||||
static_cast<float>( Lines.m_data.vertices.size() ) / ( Lines.m_data.vertices.size() + m_data.vertices.size() ) );
|
||||
m_data.vertices.insert(
|
||||
std::end( m_data.vertices ),
|
||||
std::begin( Lines.m_data.vertices ), std::end( Lines.m_data.vertices ) );
|
||||
// NOTE: we could recalculate radius with something other than brute force, but it'll do
|
||||
compute_radius();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||
void
|
||||
lines_node::create_geometry( geometrybank_handle const &Bank ) {
|
||||
|
||||
vertex_array vertices; vertices.reserve( m_data.vertices.size() );
|
||||
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
vertices.emplace_back(
|
||||
vertex.position - m_data.origin,
|
||||
vertex.normal,
|
||||
vertex.texture );
|
||||
}
|
||||
m_data.geometry = GfxRenderer.Insert( vertices, Bank, GL_LINES );
|
||||
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
|
||||
}
|
||||
|
||||
// calculates node's bounding radius
|
||||
void
|
||||
lines_node::compute_radius() {
|
||||
|
||||
auto squaredradius { 0.0 };
|
||||
for( auto const &vertex : m_data.vertices ) {
|
||||
squaredradius = std::max(
|
||||
squaredradius,
|
||||
glm::length2( vertex.position - m_data.area.center ) );
|
||||
}
|
||||
m_data.area.radius = static_cast<float>( std::sqrt( squaredradius ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
memory_node &
|
||||
memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||
@@ -279,6 +483,8 @@ memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||
*/
|
||||
} // scene
|
||||
|
||||
|
||||
|
||||
namespace editor {
|
||||
|
||||
basic_node::basic_node( scene::node_data const &Nodedata ) :
|
||||
|
||||
Reference in New Issue
Block a user