const ORIGIN_FIXED = 1 ;
const ORIGIN_CENTER = 2 ;
const ORIGIN_AUTO = 3 ;
const ORIGIN_TO = 4 ;
class Voxel
{
name = null ;
size = 0 ;
size2 = 0 ;
dirty = false ;
generation = 0 ;
$Mesh = null;
$Geometry = null;
euler = new THREE.Euler(0,0,0,'YXZ');
origin_mode = ORIGIN_CENTER ;
Origin = new V3() ;
Origin_to = new V3() ;
Obb_min = new V3() ;
Obb_max = new V3() ;
is_cloned = false ;
is_shadow = true ;
order = 50 ;
index = 0;
DEF = null;
VERTEX = null;
COLOR = null;
INDEX = null;
NORMAL = null;
constructor(name ,size)
{
this.name = name ;
this.size = Math.max(1,size);
this.size2 = this.size*this.size ;
this.DEF = [] ;
this.dirty = true ;
this.Origin.z = -0.5 ;
this.Obb_min.All(this.size);
this.Obb_max.All(0);
this.$Mesh = new THREE.Mesh();
this.$Mesh.material = µB.$D3.MATERIAL["normal"];
µB.$D3.$Root.add(this.$Mesh);
}
Dispose()
{
if( this.$Mesh )
{
µB.$D3.$Root.remove(this.$Mesh);
this.$Mesh =null;
}
if( this.$Geometry )
{ this.$Geometry.dispose();
this.$Geometry = null;
}
}
Index(x, y, z)
{ return x + z*this.size + y*this.size2 ;
}
Dirty()
{ this.dirty = true ;
µB.$Sprite.DIRTY[this.name] = true ;
}
Finalize()
{
this.$Geometry = new THREE.BufferGeometry();
this.$Geometry.setIndex( this.INDEX ) ;
this.$Geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( this.VERTEX, 3 ) );
this.$Geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( this.COLOR, 4 ) );
if( this.NORMAL.length )
{ this.$Geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( this.NORMAL, 3 ) );
}
else
{ this.$Geometry.computeVertexNormals();
}
this.$Mesh.geometry = this.$Geometry ;
this.$Mesh.receiveShadow = this.is_shadow;
this.$Mesh.castShadow = this.is_shadow;
this.$Mesh.renderOrder = this.order;
this.VERTEX = null;
this.COLOR = null;
this.INDEX = null;
this.NORMAL = null;
}
SetOrigin( mode, x,y,z )
{
this.origin_mode = mode ;
if( mode === ORIGIN_TO )
{
this.Origin_to.Set(x-.5,y-.5,z-.5);
}
this.ProcessOBB() ;
}
ProcessOBB()
{
if( this.$Geometry && this.index )
{
if( this.dirty )
{
}
else if( this.origin_mode == ORIGIN_FIXED )
{
}
else
{
if( this.origin_mode === ORIGIN_TO )
{
var $x = -this.Origin_to.x ;
var $y = -this.Origin_to.y ;
var $z = -this.Origin_to.z ;
}
else
{
var $x = -((this.Obb_max.x +1 - this.Obb_min.x)/2 + this.Obb_min.x) ;
var $y = -((this.Obb_max.y +1 - this.Obb_min.y)/2 + this.Obb_min.y) ;
var $z = -((this.Obb_max.z +1 - this.Obb_min.z)/2 + this.Obb_min.z) ;
}
let $xr = $x - this.Origin.x ;
let $yr = $y - this.Origin.y ;
let $zr = $z - this.Origin.z ;
this.$Geometry.applyMatrix4( new THREE.Matrix4().makeTranslation($xr,$yr,$zr) );
this.Origin.Set($x,$y,$z) ;
if( this.origin_mode === ORIGIN_AUTO )
{
}
else
{
this.origin_mode = ORIGIN_FIXED ;
}
}
}
}
Is(x, y, z)
{
if( x<0 || y<0 || z<0 )
{ return false;
}
else if( x>=this.size || y>=this.size || z>=this.size )
{ return false;
}
else
{ let index = this.Index(x,y,z);
return this.DEF[index] ?? 0;
}
}
Face( $Rgba )
{
this.COLOR.push( $Rgba.r, $Rgba.g, $Rgba.b, $Rgba.a );
this.COLOR.push( $Rgba.r, $Rgba.g, $Rgba.b, $Rgba.a );
this.COLOR.push( $Rgba.r, $Rgba.g, $Rgba.b, $Rgba.a );
this.COLOR.push( $Rgba.r, $Rgba.g, $Rgba.b, $Rgba.a );
/*
$Structure.$Object.UV.push( $Structure.$Object.VERTEX[i]/r + $Structure.$Object.VERTEX[i+2]/r, $Structure.$Object.VERTEX[i+1]/r ); i+=3;
$Structure.$Object.UV.push( $Structure.$Object.VERTEX[i]/r + $Structure.$Object.VERTEX[i+2]/r, $Structure.$Object.VERTEX[i+1]/r ); i+=3;
$Structure.$Object.UV.push( $Structure.$Object.VERTEX[i]/r + $Structure.$Object.VERTEX[i+2]/r, $Structure.$Object.VERTEX[i+1]/r ); i+=3;
$Structure.$Object.UV.push( $Structure.$Object.VERTEX[i]/r + $Structure.$Object.VERTEX[i+2]/r, $Structure.$Object.VERTEX[i+1]/r ); i+=3;
*/
this.INDEX.push( this.index, this.index+1, this.index+2);
this.INDEX.push( this.index+1, this.index+3, this.index+2 );
this.index +=4;
}
Cube( $bloc, $x, $y, $z )
{
this.Obb_min.Min($x,$y,$z);
this.Obb_max.Max($x,$y,$z);
var Y = [];
Y[0] = $y + this.Origin.y ;
Y[1] = Y[0] + 1;
var X = [[],[]];
var Z = [[],[]];
X[0][0] = X[0][2] = $x + this.Origin.x ;
X[0][1] = X[0][3] = X[0][0] +1 ;
Z[0][0] = Z[0][1] = $z + this.Origin.z ;
Z[0][2] = Z[0][3] = Z[0][0] +1;
X[1][0] = X[0][0]; X[1][1] = X[0][1];
X[1][2] = X[0][2]; X[1][3] = X[0][3];
Z[1][0] = Z[0][0]; Z[1][1] = Z[0][1];
Z[1][2] = Z[0][2]; Z[1][3] = Z[0][3];
var $is_left = this.Is($x-1,$y,$z);
var $is_right = this.Is($x+1,$y,$z);
var $is_front = this.Is($x,$y,$z+1);
var $is_back = this.Is($x,$y,$z-1);
var $is_top = this.Is($x,$y+1,$z);
var $is_down = this.Is($x,$y-1,$z);
var $Rgba = µB.$Config.Color2Rgba($bloc) ;
if( ! $is_back )
{
this.VERTEX.push( X[1][0],Y[1],Z[1][0] );
this.VERTEX.push( X[1][1],Y[1],Z[1][1] );
this.VERTEX.push( X[0][0],Y[0],Z[0][0] );
this.VERTEX.push( X[0][1],Y[0],Z[0][1] );
this.Face($Rgba);
}
if( ! $is_front )
{
this.VERTEX.push( X[1][2],Y[1],Z[1][2] );
this.VERTEX.push( X[0][2],Y[0],Z[0][2] );
this.VERTEX.push( X[1][3],Y[1],Z[1][3] );
this.VERTEX.push( X[0][3],Y[0],Z[0][3] );
this.Face($Rgba);
}
if( ! $is_left )
{
this.VERTEX.push( X[0][0],Y[0],Z[0][0] );
this.VERTEX.push( X[0][2],Y[0],Z[0][2] );
this.VERTEX.push( X[1][0],Y[1],Z[1][0] );
this.VERTEX.push( X[1][2],Y[1],Z[1][2] );
this.Face($Rgba);
}
if( ! $is_right )
{
this.VERTEX.push( X[0][1],Y[0],Z[0][1] );
this.VERTEX.push( X[1][1],Y[1],Z[1][1] );
this.VERTEX.push( X[0][3],Y[0],Z[0][3] );
this.VERTEX.push( X[1][3],Y[1],Z[1][3] );
this.Face($Rgba);
}
if( ! $is_top )
{
this.VERTEX.push( X[1][0],Y[1],Z[1][0] );
this.VERTEX.push( X[1][2],Y[1],Z[1][2] );
this.VERTEX.push( X[1][1],Y[1],Z[1][1] );
this.VERTEX.push( X[1][3],Y[1],Z[1][3] );
this.Face($Rgba);
}
if( ! $is_down )
{
this.VERTEX.push( X[0][0],Y[0],Z[0][0] );
this.VERTEX.push( X[0][1],Y[0],Z[0][1] );
this.VERTEX.push( X[0][2],Y[0],Z[0][2] );
this.VERTEX.push( X[0][3],Y[0],Z[0][3] );
this.Face($Rgba);
}
}
Peek(x, y, z)
{
x = Math.round(x) ;
y = Math.round(y) ;
z = Math.round(z) ;
if( x>=0 && x< this.size )
{ if( y>=0 && y< this.size )
{ if( z>=0 && z< this.size2 )
{
let index = this.Index(x,y,z);
return this.DEF[index] ?? 0 ;
}
}
}
return -1 ;
}
Poke( $color, $x,$y,$z )
{
$x = Math.round($x) ;
$y = Math.round($y) ;
$z = Math.round($z) ;
if( $x>=0 && $x< this.size )
{ if( $z>=0 && $z< this.size )
{ if( $y>=0 && $y< this.size2 )
{
let index = this.Index($x,$y,$z);
this.DEF[index] = $color;
}
}
}
}
Define( DEF )
{
for( let val of DEF )
{ this.DEF.push(val*1);
}
}
Reset()
{
this.VERTEX = [];
this.COLOR = [];
this.INDEX = [];
this.NORMAL = [];
this.index = 0 ;
if( this.$Geometry )
{
this.$Geometry.dispose();
this.$Geometry = null ;
}
}
Build()
{
if( this.DEF.length == 0 )
{
this.DEF = [1] ;
}
if( this.dirty )
{
this.generation ++ ;
this.Reset();
for( let i in this.DEF )
{
let x = i % this.size ;
let y = Math.floor(i / this.size2);
let z = Math.floor((i-y*this.size2) / this.size) ;
let bloc = this.DEF[i]??0;
if( bloc )
{ this.Cube(bloc, x,y,z) ;
}
}
this.Finalize();
this.dirty = false ;
this.ProcessOBB();
}
}
};