/* Copyright 2005 Nicholas Bishop * * This file is part of SharpConstruct. * * SharpConstruct is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * SharpConstruct is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SharpConstruct; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Create.hh" #include "MeshHistory.h" #include "Optimized.h" using SharpConstruct::Create::Cube; using SharpConstruct::Optimized::Point3D; Cube::Cube( const unsigned c, const unsigned r, const unsigned s ) : rows_( r ), cols_( c ), stacks_( s ) {} bool Cube::operator()() { create_vertices_(); create_polygons_(); return true; } void Cube::create_vertices_() { create_back_vertices_(); create_top_vertices_(); create_front_vertices_(); create_bottom_vertices_(); create_left_vertices_(); create_right_vertices_(); } void Cube::create_back_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); for( unsigned y = 0; y < rows_; ++y ) for( unsigned x = 0; x < cols_; ++x ) mesh.VertexLocations().push_back ( Point3D( x, y, 0 ) ); } void Cube::create_top_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); top_start_ = mesh.VertexLocations().size(); for( unsigned z = 1; z < stacks_; ++z ) for( unsigned x = 0; x < cols_; ++x ) mesh.VertexLocations().push_back ( Point3D( x, rows_ - 1, z ) ); } void Cube::create_front_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); front_start_ = mesh.VertexLocations().size(); for( unsigned y = 1; y < rows_; ++y ) for( unsigned x = 0; x < cols_; ++x ) mesh.VertexLocations().push_back ( Point3D( x, rows_ - y - 1, stacks_ - 1 ) ); } void Cube::create_bottom_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); bottom_start_ = mesh.VertexLocations().size(); for( unsigned z = 1; z < stacks_ - 1; ++z ) for( unsigned x = 0; x < cols_; ++x ) mesh.VertexLocations().push_back ( Point3D( x, 0, stacks_ - z - 1 ) ); } void Cube::create_left_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); left_start_ = mesh.VertexLocations().size(); for( unsigned y = 1; y < rows_ - 1; ++y ) for( unsigned z = 1; z < stacks_ - 1; z++ ) mesh.VertexLocations().push_back ( Point3D( 0, y, z ) ); } void Cube::create_right_vertices_() { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); right_start_ = mesh.VertexLocations().size(); for( unsigned y = 1; y < rows_ - 1; ++y ) for( unsigned z = 1; z < stacks_ - 1; z++ ) mesh.VertexLocations().push_back ( Point3D( cols_ - 1, y, z ) ); right_end_ = mesh.VertexLocations().size(); } void Cube::create_polygons_() const { create_main_polygon_strip_(); create_left_and_right_polygons_(); create_vertical_connections_(); create_horizontal_connections_(); create_left_corners_(); create_right_corners_(); } void Cube::create_main_polygon_strip_() const { const unsigned f_end = rows_ * 2 + stacks_ * 2 - 5; for( unsigned i = 0; i < f_end; ++i ) { for( unsigned j = 0; j < cols_ - 1; ++j ) { const unsigned p1( i * cols_ + j ); const unsigned p2( ( i + 1 ) * cols_ + j ); add_quad_( p2, p2 + 1, p1 + 1, p1 ); } } connect_back_to_bottom_(); } void Cube::connect_back_to_bottom_() const { for( unsigned i = 0; i < cols_ - 1; ++i ) { const unsigned p( left_start_ - cols_ + i ); add_quad_( i, i + 1, p + 1, p ); } } void Cube::create_left_and_right_polygons_() const { const unsigned side_offset( stacks_ - 2 ); for( unsigned y = 0; y < rows_ - 3; ++y ) { for( unsigned z( 0 ); z < stacks_ - 3; ++z ) { // Left const unsigned p1( left_start_ + y * side_offset + z ); const unsigned p2( left_start_ + ( y + 1 ) * side_offset + z ); add_quad_( p1, p1 + 1, p2 + 1, p2 ); // Right const unsigned p3( right_start_ + ( y + 1 ) * side_offset + z ); const unsigned p4( right_start_ + y * side_offset + z ); add_quad_( p3, p3 + 1, p4 + 1, p4 ); } } } void Cube::create_vertical_connections_() const { const unsigned side_offset( stacks_ - 2 ); for( unsigned z = 1; z < stacks_ - 2; ++z ) { // Connect the left to the top const unsigned p1( right_start_ - stacks_ + 2 + z ); const unsigned p2( rows_ * cols_ + ( z - 1 ) * cols_ ); add_quad_( p2 + cols_, p2, p1 - 1, p1 ); // Connect the left to the bottom const unsigned p3( left_start_ - z + side_offset ); const unsigned p4( bottom_start_ + z * cols_ ); add_quad_( p4, p4 - cols_, p3, p3 - 1 ); // Connect the right to the top const unsigned p5( right_end_ - stacks_ + 2 + z ); const unsigned p6( rows_ * cols_ + z * cols_ - 1 ); add_quad_( p5, p5 - 1, p6, p6 + cols_ ); // Connect the right to the bottom const unsigned p7( right_start_ - z + side_offset ); const unsigned p8( bottom_start_ + ( z + 1 ) * cols_ - 1 ); add_quad_( p7 - 1, p7, p8 - cols_, p8 ); } } void Cube::create_horizontal_connections_() const { const unsigned side_offset( stacks_ - 2 ); for( unsigned y = 1; y < rows_ - 2; ++y ) { // Connect the left to the back const unsigned p1( left_start_ + ( y - 1 ) * side_offset ); const unsigned p2( y * cols_ ); add_quad_( p1, p1 + side_offset, p2 + cols_, p2 ); // Connect the left to the front const unsigned p3( left_start_ + y * side_offset - 1 ); const unsigned p4( front_start_ + ( rows_ - y - 3 ) * cols_ ); add_quad_( p4 + cols_, p4, p3 + side_offset, p3 ); // Connect the right to the back const unsigned p5( right_start_ + ( y - 1 ) * side_offset ); const unsigned p6( ( y + 1 ) * cols_ - 1 ); add_quad_( p6, p6 + cols_, p5 + side_offset, p5 ); // Connect the right to the front const unsigned p7( right_start_ + y * side_offset - 1 ); const unsigned p8( front_start_ + ( rows_ - y - 2 ) * cols_ - 1 ); add_quad_( p7, p7 + side_offset, p8, p8 + cols_ ); } } void Cube::create_left_corners_() const { const unsigned side_offset( stacks_ - 2 ); add_quad_( left_start_ - cols_, left_start_, cols_, 0 ); add_quad_( ( rows_ - 1 ) * cols_, ( rows_ - 2 ) * cols_, left_start_ + ( rows_ - 3 ) * side_offset, top_start_ ); add_quad_( left_start_ + ( rows_ - 2 ) * side_offset - 1, front_start_, top_start_ + ( stacks_ - 2 ) * cols_, top_start_ + ( stacks_ - 3 ) * cols_ ); add_quad_( left_start_ + stacks_ - 3, bottom_start_, front_start_ + ( rows_ - 2 ) * cols_, front_start_ + ( rows_ - 3 ) * cols_ ); } void Cube::create_right_corners_() const { const unsigned side_offset( stacks_ - 2 ); add_quad_( cols_ - 1, cols_ * 2 - 1, right_start_, left_start_ - 1 ); add_quad_( top_start_ + cols_ - 1, right_start_ + ( rows_ - 3 ) * side_offset, ( rows_ - 1 ) * cols_ - 1, ( rows_ - 0 ) * cols_ - 1 ); add_quad_( top_start_ + ( stacks_ - 2 ) * cols_ - 1, top_start_ + ( stacks_ - 1 ) * cols_ - 1, front_start_ + cols_ - 1, right_start_ + ( rows_ - 2 ) * side_offset - 1 ); add_quad_( front_start_ + ( rows_ - 2 ) * cols_ - 1, front_start_ + ( rows_ - 1 ) * cols_ - 1, bottom_start_ + cols_ - 1, right_start_ + stacks_ - 3 ); } void Cube::add_quad_( const unsigned p1, const unsigned p2, const unsigned p3, const unsigned p4 ) const { Mesh& mesh( MeshHistory::Instance().GetCurrentMesh() ); mesh.Quads().push_back( Quad( p1, p2, p3, p4 ) ); }