* brushexport plugin: write Kd (diffuse color) and map_Kd (diffuse map) data to .mtl

* brushexport plugin fix: invert Y during YZ swap; invert V of UV coords (correct texturing)
	* brushexport plugin: default to 'Don't collapse' option
q3map2:	* obj export: save in popular 'Y = Up, -Z = Forward' format
	* picomodel::obj: load as popular 'Y = Up, -Z = Forward' format
	* picomodel::obj: fix support of back references in faces
This commit is contained in:
Garux 2019-01-10 00:44:27 +03:00
parent e7fbe45319
commit 034f06f18d
4 changed files with 56 additions and 37 deletions

View File

@ -178,7 +178,11 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
std::string mtlFile = objFile.substr( 0, objFile.length() - 4 ) + ".mtl";
std::set<std::string> materials;
typedef std::pair<std::string, Colour3> Material;
auto materials_comparator = []( const Material& ma1, const Material& ma2 ) {
return ma1.first < ma2.first;
};
auto materials = std::set<Material, decltype( materials_comparator )>( materials_comparator );
TextFileOutputStream out( objFile.c_str() );
@ -218,7 +222,7 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
// material
if ( expmat && mode == COLLAPSE_ALL ) {
out << "usemtl material" << "\n\n";
materials.insert( "material" );
materials.insert( std::make_pair( std::string( "material" ), Colour3( 0.5, 0.5, 0.5 ) ) );
}
for ( std::list<const Face*>::const_iterator it( git->faces.begin() ); it != end; ++it )
@ -226,8 +230,12 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
const Winding& w( ( *it )->getWinding() );
// vertices
for ( size_t i = 0; i < w.numpoints; ++i )
out << "v " << FloatFormat( w[i].vertex.x(), 1, 6 ) << " " << FloatFormat( w[i].vertex.z(), 1, 6 ) << " " << FloatFormat( w[i].vertex.y(), 1, 6 ) << "\n";
size_t i = w.numpoints;
do{
--i;
out << "v " << FloatFormat( w[i].vertex.x(), 1, 6 ) << " " << FloatFormat( w[i].vertex.z(), 1, 6 ) << " " << FloatFormat( -w[i].vertex.y(), 1, 6 ) << "\n";
}
while( i != 0 );
}
out << "\n";
@ -236,8 +244,12 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
const Winding& w( ( *it )->getWinding() );
// texcoords
for ( size_t i = 0; i < w.numpoints; ++i )
out << "vt " << FloatFormat( w[i].texcoord.x(), 1, 6 ) << " " << FloatFormat( w[i].texcoord.y(), 1, 6 ) << "\n";
size_t i = w.numpoints;
do{
--i;
out << "vt " << FloatFormat( w[i].texcoord.x(), 1, 6 ) << " " << FloatFormat( -w[i].texcoord.y(), 1, 6 ) << "\n";
}
while( i != 0 );
}
for ( std::list<const Face*>::const_iterator it( git->faces.begin() ); it != end; ++it )
@ -247,18 +259,24 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
// faces
StringOutputStream faceLine( 256 );
faceLine << "\nf";
for ( size_t i = 0; i < w.numpoints; ++i, ++vertex_count )
{
faceLine << " " << vertex_count + 1 << "/" << vertex_count + 1;
size_t i = w.numpoints;
do{
--i;
++vertex_count;
faceLine << " " << vertex_count << "/" << vertex_count;
}
while( i != 0 );
if ( mode != COLLAPSE_ALL ) {
materials.insert( ( *it )->getShader().getShader() );
materials.insert( std::make_pair( std::string( ( *it )->getShader().getShader() ), ( *it )->getShader().state()->getTexture().color ) );
brushMaterials.insert( String_Pair( ( *it )->getShader().getShader(), faceLine.c_str() ) );
}
else {
out << faceLine.c_str();
}
}
if ( mode != COLLAPSE_ALL ) {
@ -297,14 +315,19 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
outMtl << "# Wavefront material file exported with NetRadiants brushexport plugin.\n";
outMtl << "# Material Count: " << (const Unsigned)materials.size() << "\n\n";
for ( std::set<std::string>::const_iterator it( materials.begin() ); it != materials.end(); ++it )
for ( std::set<std::pair<std::string, Colour3>>::const_iterator it( materials.begin() ); it != materials.end(); ++it )
{
if ( limNames && it->size() > MAX_MATERIAL_NAME ) {
outMtl << "newmtl " << it->substr( it->size() - MAX_MATERIAL_NAME, it->size() ).c_str() << "\n";
const std::string& str = it->first;
const Colour3& clr = it->second;
if ( limNames && str.size() > MAX_MATERIAL_NAME ) {
outMtl << "newmtl " << str.substr( str.size() - MAX_MATERIAL_NAME, str.size() ).c_str() << "\n";
}
else {
outMtl << "newmtl " << it->c_str() << "\n";
outMtl << "newmtl " << str.c_str() << "\n";
}
outMtl << "Kd " << clr.x() << " " << clr.y() << " " << clr.z() << "\n";
outMtl << "map_Kd " << str.c_str() << "\n";
}
}
@ -320,6 +343,7 @@ ForEachFace( ExportData& _exporter )
{}
void visit( Face& face ) const {
if( face.contributes() )
exporter.AddBrushFace( face );
}

View File

@ -89,6 +89,7 @@ create_w_plugplug2( void ){
gtk_box_pack_start( GTK_BOX( vbox4 ), r_nocollapse, FALSE, FALSE, 0 );
gtk_radio_button_set_group( GTK_RADIO_BUTTON( r_nocollapse ), r_collapse_group );
r_collapse_group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( r_nocollapse ) );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( r_nocollapse ), TRUE );
vbox3 = gtk_vbox_new( FALSE, 0 );
gtk_widget_set_name( vbox3, "vbox3" );

View File

@ -779,17 +779,15 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
}
}
/* fix useless back references */
/* todo: check if this works as it is supposed to */
/* assign new indices */
if ( iv [ i ] < 0 ) {
iv [ i ] = ( numVerts - iv [ i ] );
iv [ i ] = ( numVerts + iv [ i ] + 1 );
}
if ( ivt[ i ] < 0 ) {
ivt[ i ] = ( numUVs - ivt[ i ] );
ivt[ i ] = ( numUVs + ivt[ i ] + 1 );
}
if ( ivn[ i ] < 0 ) {
ivn[ i ] = ( numNormals - ivn[ i ] );
ivn[ i ] = ( numNormals + ivn[ i ] + 1 );
}
/* validate indices */
@ -807,8 +805,8 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
/* get vertex data */
verts[ i ][ 0 ] = vertexData[ iv[ i ] - 1 ].v[ 0 ];
verts[ i ][ 1 ] = vertexData[ iv[ i ] - 1 ].v[ 1 ];
verts[ i ][ 2 ] = vertexData[ iv[ i ] - 1 ].v[ 2 ];
verts[ i ][ 1 ] = -vertexData[ iv[ i ] - 1 ].v[ 2 ];
verts[ i ][ 2 ] = vertexData[ iv[ i ] - 1 ].v[ 1 ];
}
/* set vertex normal */
if ( has_vn ) {
@ -819,8 +817,8 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
/* get normal data */
normals[ i ][ 0 ] = vertexData[ ivn[ i ] - 1 ].vn[ 0 ];
normals[ i ][ 1 ] = vertexData[ ivn[ i ] - 1 ].vn[ 1 ];
normals[ i ][ 2 ] = vertexData[ ivn[ i ] - 1 ].vn[ 2 ];
normals[ i ][ 1 ] = -vertexData[ ivn[ i ] - 1 ].vn[ 2 ];
normals[ i ][ 2 ] = vertexData[ ivn[ i ] - 1 ].vn[ 1 ];
}
/* set texture coordinate */
if ( has_vt ) {
@ -831,8 +829,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
/* get uv coord data */
coords[ i ][ 0 ] = vertexData[ ivt[ i ] - 1 ].vt[ 0 ];
coords[ i ][ 1 ] = vertexData[ ivt[ i ] - 1 ].vt[ 1 ];
coords[ i ][ 1 ] = -coords[ i ][ 1 ];
coords[ i ][ 1 ] = -vertexData[ ivt[ i ] - 1 ].vt[ 1 ];
}
#ifdef DEBUG_PM_OBJ_EX
printf( "(%4d",iv[ i ] );
@ -852,10 +849,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
/* read the actual data we need to assign all the crap */
/* to our current pico surface */
if ( has_v ) {
int max = 3;
if ( have_quad ) {
max = 4;
}
const int max = have_quad? 4 : 3;
/* assign all surface information */
for ( i = 0; i < max; i++ )

View File

@ -98,13 +98,13 @@ static void ConvertSurfaceToOBJ( FILE *f, bspModel_t *model, int modelNum, bspDr
v = i + ds->firstVert;
dv = &bspDrawVerts[ v ];
fprintf( f, "# vertex %d\r\n", i + objVertexCount + 1 );
fprintf( f, "v %f %f %f\r\n", dv->xyz[ 0 ], dv->xyz[ 1 ], dv->xyz[ 2 ] );
fprintf( f, "vn %f %f %f\r\n", dv->normal[ 0 ], dv->normal[ 1 ], dv->normal[ 2 ] );
fprintf( f, "v %f %f %f\r\n", dv->xyz[ 0 ], dv->xyz[ 2 ], -dv->xyz[ 1 ] );
fprintf( f, "vn %f %f %f\r\n", dv->normal[ 0 ], dv->normal[ 2 ], -dv->normal[ 1 ] );
if ( lightmapsAsTexcoord ) {
fprintf( f, "vt %f %f\r\n", dv->lightmap[0][0], 1.0 - dv->lightmap[0][1] );
fprintf( f, "vt %f %f\r\n", dv->lightmap[0][0], -dv->lightmap[0][1] );
}
else{
fprintf( f, "vt %f %f\r\n", dv->st[ 0 ], 1.0 - dv->st[ 1 ] );
fprintf( f, "vt %f %f\r\n", dv->st[ 0 ], -dv->st[ 1 ] );
}
}