* brush.icosahedron.truncate option
This commit is contained in:
parent
e1f3b25bc6
commit
8b460b5318
|
|
@ -327,75 +327,94 @@ void Brush_ConstructRock( Brush& brush, const AABB& bounds, std::size_t sides, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "quickhull/QuickHull.hpp"
|
||||||
namespace icosahedron{
|
namespace icosahedron{
|
||||||
|
|
||||||
#define X .525731112119133606
|
constexpr double X = .525731112119133606;
|
||||||
#define Z .850650808352039932
|
constexpr double Z = .850650808352039932;
|
||||||
|
// 12 vertices
|
||||||
static float vdata[12][3] = {
|
static const DoubleVector3 vdata[12] = {
|
||||||
{ -X, 0.0, Z}, {X, 0.0, Z}, { -X, 0.0, -Z}, {X, 0.0, -Z},
|
{ -X, 0.0, Z}, {X, 0.0, Z}, { -X, 0.0, -Z}, {X, 0.0, -Z},
|
||||||
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
|
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
|
||||||
{Z, X, 0.0}, { -Z, X, 0.0}, {Z, -X, 0.0}, { -Z, -X, 0.0}
|
{Z, X, 0.0}, { -Z, X, 0.0}, {Z, -X, 0.0}, { -Z, -X, 0.0}
|
||||||
};
|
};
|
||||||
static unsigned int tindices[20][3] = {
|
// 20 faces
|
||||||
|
static constexpr unsigned int tindices[20][3] = {
|
||||||
{0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1},
|
{0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1},
|
||||||
{8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3},
|
{8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3},
|
||||||
{7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6},
|
{7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6},
|
||||||
{6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}
|
{6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}
|
||||||
};
|
};
|
||||||
|
|
||||||
void normalize( float* a ) {
|
void drawtri( const DoubleVector3& a, const DoubleVector3& b, const DoubleVector3& c, std::size_t subdivisions, bool truncate, std::vector<quickhull::Vector3<double>>& pointCloud ) {
|
||||||
float d = sqrt( a[0] * a[0] + a[1] * a[1] + a[2] * a[2] );
|
if( subdivisions == 0 ) {
|
||||||
a[0] /= d;
|
const auto push = [&pointCloud]( const DoubleVector3& p ){
|
||||||
a[1] /= d;
|
pointCloud.push_back( quickhull::Vector3<double>( p.x(), p.y(), p.z() ) );
|
||||||
a[2] /= d;
|
};
|
||||||
}
|
if( truncate ){ // this is not quite correct after subdivision performed :thinking:
|
||||||
|
push( ( a * ( 2.0 / 3.0 ) ) + ( b * ( 1.0 / 3.0 ) ) );
|
||||||
void drawtri( float* a, float* b, float* c, std::size_t subdivisions, Brush& brush, float radius, const Vector3& mid, const char* shader, const TextureProjection& projection ) {
|
push( ( a * ( 1.0 / 3.0 ) ) + ( b * ( 2.0 / 3.0 ) ) );
|
||||||
if( subdivisions <= 0 ) {
|
push( ( a * ( 2.0 / 3.0 ) ) + ( c * ( 1.0 / 3.0 ) ) );
|
||||||
brush.addPlane( Vector3( a[0], a[1], a[2] ) * radius + mid,
|
push( ( a * ( 1.0 / 3.0 ) ) + ( c * ( 2.0 / 3.0 ) ) );
|
||||||
Vector3( b[0], b[1], b[2] ) * radius + mid,
|
push( ( b * ( 2.0 / 3.0 ) ) + ( c * ( 1.0 / 3.0 ) ) );
|
||||||
Vector3( c[0], c[1], c[2] ) * radius + mid,
|
push( ( b * ( 1.0 / 3.0 ) ) + ( c * ( 2.0 / 3.0 ) ) );
|
||||||
shader, projection );
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
float ab[3], ac[3], bc[3];
|
push( a );
|
||||||
for( int i = 0; i < 3; i++ ) {
|
push( b );
|
||||||
ab[i] = ( a[i] + b[i] ) / 2;
|
push( c );
|
||||||
ac[i] = ( a[i] + c[i] ) / 2;
|
|
||||||
bc[i] = ( b[i] + c[i] ) / 2;
|
|
||||||
}
|
}
|
||||||
normalize( ab );
|
}
|
||||||
normalize( ac );
|
else{
|
||||||
normalize( bc );
|
const DoubleVector3 ab = vector3_normalised( a + b );
|
||||||
drawtri( a, ab, ac, subdivisions - 1, brush, radius, mid, shader, projection );
|
const DoubleVector3 ac = vector3_normalised( a + c );
|
||||||
drawtri( b, bc, ab, subdivisions - 1, brush, radius, mid, shader, projection );
|
const DoubleVector3 bc = vector3_normalised( b + c );
|
||||||
drawtri( c, ac, bc, subdivisions - 1, brush, radius, mid, shader, projection );
|
|
||||||
drawtri( ab, bc, ac, subdivisions - 1, brush, radius, mid, shader, projection ); //<--Comment this line and sphere looks really cool!
|
drawtri( a, ab, ac, subdivisions - 1, truncate, pointCloud );
|
||||||
|
drawtri( b, bc, ab, subdivisions - 1, truncate, pointCloud );
|
||||||
|
drawtri( c, ac, bc, subdivisions - 1, truncate, pointCloud );
|
||||||
|
drawtri( ab, bc, ac, subdivisions - 1, truncate, pointCloud ); //<--Comment this line and sphere looks really cool!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Brush_ConstructIcosahedron( Brush& brush, const AABB& bounds, std::size_t subdivisions, const char* shader, const TextureProjection& projection ){
|
void Brush_ConstructIcosahedron( Brush& brush, const AABB& bounds, std::size_t subdivisions, bool truncate, const char* shader, const TextureProjection& projection ){
|
||||||
if ( Unsigned( 20 * ( 4 << subdivisions ) ) > c_brush_maxFaces ) {
|
|
||||||
globalErrorStream() << "brushIcosahedron" << ": subdivisions " << Unsigned( subdivisions ) << ": wrong sides count requested\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
brush.clear();
|
brush.clear();
|
||||||
brush.reserve( 20 * ( 4 << subdivisions ) );
|
|
||||||
|
|
||||||
float radius = max_extent( bounds.extents );
|
const float radius = max_extent( bounds.extents );
|
||||||
const Vector3& mid = bounds.origin;
|
const Vector3& mid = bounds.origin;
|
||||||
|
|
||||||
|
std::vector<quickhull::Vector3<double>> pointCloud;
|
||||||
|
|
||||||
for( int i = 0; i < 20; i++ ){
|
for( int i = 0; i < 20; i++ ){
|
||||||
drawtri( vdata[tindices[i][0]], vdata[tindices[i][1]], vdata[tindices[i][2]], subdivisions, brush, radius, mid, shader, projection );
|
drawtri( vdata[tindices[i][0]], vdata[tindices[i][1]], vdata[tindices[i][2]], subdivisions, truncate, pointCloud );
|
||||||
|
}
|
||||||
|
|
||||||
|
quickhull::QuickHull<double> quickhull;
|
||||||
|
auto hull = quickhull.getConvexHull( pointCloud, true, true );
|
||||||
|
const auto& indexBuffer = hull.getIndexBuffer();
|
||||||
|
const size_t triangleCount = indexBuffer.size() / 3;
|
||||||
|
std::vector<Plane3> planes;
|
||||||
|
for( size_t i = 0; i < triangleCount; ++i ) {
|
||||||
|
DoubleVector3 p[3];
|
||||||
|
for( size_t j = 0; j < 3; ++j ){
|
||||||
|
p[j] = DoubleVector3( pointCloud[indexBuffer[i * 3 + j]].x,
|
||||||
|
pointCloud[indexBuffer[i * 3 + j]].y,
|
||||||
|
pointCloud[indexBuffer[i * 3 + j]].z );
|
||||||
|
}
|
||||||
|
const Plane3 plane = plane3_for_points( p );
|
||||||
|
if( plane3_valid( plane ) ){
|
||||||
|
if( std::find_if( planes.begin(), planes.end(), [&plane]( const Plane3& pla ){ return plane3_equal( plane, pla ); } ) == planes.end() ){
|
||||||
|
planes.push_back( plane );
|
||||||
|
brush.addPlane( p[0] * radius + mid, p[1] * radius + mid, p[2] * radius + mid, shader, projection );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace icosahedron
|
} //namespace icosahedron
|
||||||
|
|
||||||
void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){
|
void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds, std::size_t sides, bool option, const char* shader, const TextureProjection& projection ){
|
||||||
switch ( type )
|
switch ( type )
|
||||||
{
|
{
|
||||||
case eBrushCuboid:
|
case eBrushCuboid:
|
||||||
|
|
@ -448,7 +467,7 @@ void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds,
|
||||||
command << "brushIcosahedron" << " -subdivisions " << Unsigned( sides );
|
command << "brushIcosahedron" << " -subdivisions " << Unsigned( sides );
|
||||||
UndoableCommand undo( command.c_str() );
|
UndoableCommand undo( command.c_str() );
|
||||||
|
|
||||||
icosahedron::Brush_ConstructIcosahedron( brush, bounds, sides, shader, projection );
|
icosahedron::Brush_ConstructIcosahedron( brush, bounds, sides, option, shader, projection );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -802,14 +821,14 @@ const TextureProjection& TextureTransform_getDefault(){
|
||||||
return g_defaultTextureProjection;
|
return g_defaultTextureProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader ){
|
void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, bool option, const char* shader ){
|
||||||
if ( GlobalSelectionSystem().countSelected() != 0 ) {
|
if ( GlobalSelectionSystem().countSelected() != 0 ) {
|
||||||
const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
|
const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
|
||||||
|
|
||||||
Brush* brush = Node_getBrush( path.top() );
|
Brush* brush = Node_getBrush( path.top() );
|
||||||
if ( brush != 0 ) {
|
if ( brush != 0 ) {
|
||||||
AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified
|
const AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified
|
||||||
Brush_ConstructPrefab( *brush, type, bounds, sides, shader, TextureTransform_getDefault() );
|
Brush_ConstructPrefab( *brush, type, bounds, sides, option, shader, TextureTransform_getDefault() );
|
||||||
SceneChangeNotify();
|
SceneChangeNotify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1447,7 +1466,7 @@ BrushMakeSided( std::size_t count )
|
||||||
: m_count( count ){
|
: m_count( count ){
|
||||||
}
|
}
|
||||||
void set(){
|
void set(){
|
||||||
Scene_BrushConstructPrefab( GlobalSceneGraph(), eBrushPrism, m_count, TextureBrowser_GetSelectedShader() );
|
Scene_BrushConstructPrefab( GlobalSceneGraph(), eBrushPrism, m_count, false, TextureBrowser_GetSelectedShader() );
|
||||||
}
|
}
|
||||||
typedef MemberCaller<BrushMakeSided, &BrushMakeSided::set> SetCaller;
|
typedef MemberCaller<BrushMakeSided, &BrushMakeSided::set> SetCaller;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace scene
|
||||||
class Graph;
|
class Graph;
|
||||||
class Node;
|
class Node;
|
||||||
}
|
}
|
||||||
void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader );
|
void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, bool option, const char* shader );
|
||||||
class AABB;
|
class AABB;
|
||||||
void Scene_BrushResize_Cuboid( scene::Node*& node, const AABB& bounds );
|
void Scene_BrushResize_Cuboid( scene::Node*& node, const AABB& bounds );
|
||||||
void Brush_ConstructPlacehoderCuboid( scene::Node& node, const AABB& bounds );
|
void Brush_ConstructPlacehoderCuboid( scene::Node& node, const AABB& bounds );
|
||||||
|
|
|
||||||
|
|
@ -366,8 +366,7 @@ void DoProjectSettings(){
|
||||||
|
|
||||||
void DoSides( int type, int axis ){
|
void DoSides( int type, int axis ){
|
||||||
ModalDialog dialog;
|
ModalDialog dialog;
|
||||||
//GtkEntry* sides_entry;
|
GtkWidget* spin, *toggle;
|
||||||
GtkWidget* sides_spin;
|
|
||||||
|
|
||||||
GtkWindow* window = create_dialog_window( MainFrame_getWindow(), "Arbitrary sides", G_CALLBACK( dialog_delete_callback ), &dialog );
|
GtkWindow* window = create_dialog_window( MainFrame_getWindow(), "Arbitrary sides", G_CALLBACK( dialog_delete_callback ), &dialog );
|
||||||
|
|
||||||
|
|
@ -375,20 +374,21 @@ void DoSides( int type, int axis ){
|
||||||
gtk_window_add_accel_group( window, accel );
|
gtk_window_add_accel_group( window, accel );
|
||||||
|
|
||||||
{
|
{
|
||||||
|
GtkVBox* vbox = create_dialog_vbox( 0, 0 );
|
||||||
|
gtk_container_add( GTK_CONTAINER( window ), GTK_WIDGET( vbox ) );
|
||||||
GtkHBox* hbox = create_dialog_hbox( 4, 4 );
|
GtkHBox* hbox = create_dialog_hbox( 4, 4 );
|
||||||
gtk_container_add( GTK_CONTAINER( window ), GTK_WIDGET( hbox ) );
|
gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET( hbox ), FALSE, FALSE, 0 );
|
||||||
|
|
||||||
|
GtkLabel* label;
|
||||||
{
|
{
|
||||||
GtkLabel* label = GTK_LABEL( gtk_label_new( "Sides:" ) );
|
label = GTK_LABEL( gtk_label_new( "Sides:" ) );
|
||||||
gtk_widget_show( GTK_WIDGET( label ) );
|
gtk_widget_show( GTK_WIDGET( label ) );
|
||||||
gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET( label ), FALSE, FALSE, 0 );
|
gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET( label ), FALSE, FALSE, 0 );
|
||||||
}
|
}
|
||||||
// {
|
{
|
||||||
// GtkEntry* entry = GTK_ENTRY( gtk_entry_new() );
|
toggle = gtk_check_button_new_with_label( "Truncate" );
|
||||||
// gtk_widget_show( GTK_WIDGET( entry ) );
|
gtk_box_pack_end( GTK_BOX( vbox ), toggle, FALSE, FALSE, 0 );
|
||||||
// gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET( entry ), FALSE, FALSE, 0 );
|
}
|
||||||
// sides_entry = entry;
|
|
||||||
// gtk_widget_grab_focus( GTK_WIDGET( entry ) );
|
|
||||||
// }
|
|
||||||
{
|
{
|
||||||
GtkAdjustment* adj;
|
GtkAdjustment* adj;
|
||||||
EBrushPrefab BrushPrefabType = (EBrushPrefab)type;
|
EBrushPrefab BrushPrefabType = (EBrushPrefab)type;
|
||||||
|
|
@ -406,19 +406,19 @@ void DoSides( int type, int axis ){
|
||||||
break;
|
break;
|
||||||
case eBrushIcosahedron :
|
case eBrushIcosahedron :
|
||||||
adj = GTK_ADJUSTMENT( gtk_adjustment_new( 1, 0, 2, 1, 10, 0 ) ); //possible with 3, but buggy
|
adj = GTK_ADJUSTMENT( gtk_adjustment_new( 1, 0, 2, 1, 10, 0 ) ); //possible with 3, but buggy
|
||||||
|
gtk_widget_show( toggle );
|
||||||
|
gtk_label_set_label( label, "Subdivisions" );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
adj = GTK_ADJUSTMENT( gtk_adjustment_new( 8, 3, 31, 1, 10, 0 ) );
|
adj = GTK_ADJUSTMENT( gtk_adjustment_new( 8, 3, 31, 1, 10, 0 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* spin = gtk_spin_button_new( adj, 1, 0 );
|
spin = gtk_spin_button_new( adj, 1, 0 );
|
||||||
gtk_widget_show( spin );
|
gtk_widget_show( spin );
|
||||||
gtk_box_pack_start( GTK_BOX( hbox ), spin, FALSE, FALSE, 0 );
|
gtk_box_pack_start( GTK_BOX( hbox ), spin, FALSE, FALSE, 0 );
|
||||||
gtk_widget_set_size_request( spin, 64, -1 );
|
gtk_widget_set_size_request( spin, 64, -1 );
|
||||||
gtk_spin_button_set_numeric( GTK_SPIN_BUTTON( spin ), TRUE );
|
gtk_spin_button_set_numeric( GTK_SPIN_BUTTON( spin ), TRUE );
|
||||||
|
|
||||||
sides_spin = spin;
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
GtkVBox* vbox = create_dialog_vbox( 4 );
|
GtkVBox* vbox = create_dialog_vbox( 4 );
|
||||||
|
|
@ -438,12 +438,10 @@ void DoSides( int type, int axis ){
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( modal_dialog_show( window, dialog ) == eIDOK ) {
|
if ( modal_dialog_show( window, dialog ) == eIDOK ) {
|
||||||
// const char *str = gtk_entry_get_text( sides_entry );
|
gtk_spin_button_update ( GTK_SPIN_BUTTON( spin ) );
|
||||||
|
const int sides = static_cast<int>( gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) ) );
|
||||||
// Scene_BrushConstructPrefab( GlobalSceneGraph(), (EBrushPrefab)type, atoi( str ), TextureBrowser_GetSelectedShader() );
|
const bool option = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggle ) );
|
||||||
gtk_spin_button_update ( GTK_SPIN_BUTTON( sides_spin ) );
|
Scene_BrushConstructPrefab( GlobalSceneGraph(), (EBrushPrefab)type, sides, option, TextureBrowser_GetSelectedShader() );
|
||||||
int sides = static_cast<int>( gtk_spin_button_get_value( GTK_SPIN_BUTTON( sides_spin ) ) );
|
|
||||||
Scene_BrushConstructPrefab( GlobalSceneGraph(), (EBrushPrefab)type, sides, TextureBrowser_GetSelectedShader() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_widget_destroy( GTK_WIDGET( window ) );
|
gtk_widget_destroy( GTK_WIDGET( window ) );
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user