--[[ k_smallblocks is a Minetest mod that adds smaller blocks to minetest aswell as its own node placement prediction/system Copyright (C) 2019 Kurtzmusch This file is part of k_smallblocks k_smallblocks is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. k_smallblocks 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with k_smallblocks. If not, see . --]] -- bitmap is an array of 8 integers that can be either 0 or 1 -- it is used to indicate wich part of the node is filled with a smallblock util = {} util.table_invert = function(t) local s={} for k,v in pairs(t) do s[v]=k end return s end util.table_shallow_copy = function(t) local t2 = {} for k,v in pairs(t) do t2[k] = v end return t2 end -- does the equivalent of a bitwise OR with 2 bitmaps util.or_bitmap = function( array1, array2 ) local result = { [7] = nil } local index = 0 while (index < 8 ) do if( (array1[index] == 1) or (array2[index] == 1) ) then result[index] = 1 else result[index] = 0 end index = index + 1 end return result end util.xor_bitmap = function( bitmap1, bitmap2 ) local result = {} local index = 0 while(index<8) do if( ( (bitmap1[index] == 1) or (bitmap2[index] == 1 ) ) and ( (bitmap1[index] == 0) or (bitmap2[index] == 0 ) ) ) then result[index] = 1 else result[index] = 0 end index = index + 1 end return result end -- convert world coordinates into node coordinates, ranging from 0 to 1 util.worldPoint_to_nodePoint = function( point ) point.x = point.x + 65536.5 point.y = point.y + 65536.5 point.z = point.z + 65536.5 return { x=point.x%1, y=point.y%1, z=point.z%1 } end -- converts a point in a node into a bitmap -- input coords must be between 0 and 1 -- the bitmap is empty, except for the smallblock in the given coordinate util.nodePoint_to_bitmap = function( point ) local size = 2 -- lenght of a node in smallblocks -- floored components are indexes of a 3d array local floored_point = {} floored_point.x = math.floor( point.x*2 ) floored_point.y = math.floor( point.y*2 ) floored_point.z = math.floor( point.z*2 ) bitmap = {} local index = 0 while (index < 8) do bitmap[index] = 0 index = index + 1 end -- this is like converting a 3d array to a 1d array index = (floored_point.x) + (floored_point.y*size) + (floored_point.z*(size*size)) bitmap[index] = 1 return bitmap end util.nodePoint_to_bitmap4x4 = function( point ) local result = {} for x=0, 3, 1 do result[x] = {} for y=0, 3, 1 do result[x][y] = {} for z=0, 3, 1 do result[x][y][z] = 0 end end end local size = 4 minetest.log( "warning", point.x.."|"..point.y.."|"..point.z ) local floored_point = {} floored_point.x = math.floor( point.x*size ) floored_point.y = math.floor( point.y*size ) floored_point.z = math.floor( point.z*size ) minetest.log( "warning", point.x.."|"..point.y.."|"..point.z ) minetest.log( "error", floored_point.x.."|"..floored_point.y.."|"..floored_point.z ) result[floored_point.x][floored_point.y][floored_point.z] = 1 return result end -- this assumes only one of the values is 1 util.bitmap4x4_to_facetype = function( bitmap4x4 ) --find indexes local ix local iy local iz for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then ix = x iy = y iz = z end end end end -- count indexes at edge of array local edge_indexes = 0 if( ( ix == 0) or (ix == 3) ) then edge_indexes = edge_indexes + 1 end if( ( iy == 0) or (iy == 3) ) then edge_indexes = edge_indexes + 1 end if( ( iz == 0) or (iz == 3) ) then edge_indexes = edge_indexes + 1 end minetest.chat_send_all( ix.." "..iy.." "..iz ) if( edge_indexes == 3 ) then return "corner" end if( edge_indexes == 2 ) then return "edge" end if( edge_indexes == 1 ) then return "face" end return "unsuported" end util.bitmap4x4_to_bitmap2x2 = function( bitmap4x4 ) local result = {} local point_list = {} local i = 0 for ix=0, 3, 1 do for iy=0, 3, 1 do for iz=0, 3, 1 do if( bitmap4x4[ix][iy][iz] == 1 ) then point_list[i] = { x=ix/4.0,y=iy/4.0,z=iz/4.0 } i = i + 1 end end end end local new_point_list = {} for k, v in pairs(point_list) do minetest.log( "warning", v.x..":"..math.floor(v.x*2).." ".. v.y..":"..math.floor(v.y*2).." ".. v.z..":"..math.floor(v.z*2) ) new_point_list[k] = { x=math.floor(v.x*2), y=math.floor(v.y*2), z=math.floor(v.z*2) } end for ix=0, 1, 1 do result[ix] = {} for iy=0, 1, 1 do result[ix][iy] = {} for iz=0, 1, 1 do result[ix][iy][iz] = 0 end end end for k, v in pairs(new_point_list) do minetest.log( "none", v.x..v.y..v.z ) result[v.x][v.y][v.z] = 1 end return result end -- assumes you give it a bitmap of type edge-expanded util.bitmap4x4_expand_faces = function( bitmap4x4 ) -- remove corners for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then if( -- if its a corner ( (x==0) or (x==3) ) and ( (y==0) or (y==3) ) and ( (z==0) or (z==3) ) ) then bitmap4x4[x][y][z] = 0 end end end end end --find faces local ix local iy local iz local dimension = {} for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then ix = x iy = y iz = z end end end end local index = 0 if( (ix == 0) or (ix == 3) ) then dimension[index] = 'x' index = index + 1 end if( (iy == 0) or (iy == 3) ) then dimension[index] = 'y' index = index + 1 end if( (iz == 0) or (iz == 3) ) then dimension[index] = 'z' index = index + 1 end for k, v in pairs(dimension) do minetest.chat_send_all( v ) if( v == 'x' ) then for z=0, 3, 1 do for y=0, 3, 1 do bitmap4x4[ix][y][z] = 1 end end end if( v == 'y' ) then for x=0, 3, 1 do for z=0, 3, 1 do bitmap4x4[x][iy][z] = 1 end end end if( v == 'z' ) then for x=0, 3, 1 do for y=0, 3, 1 do bitmap4x4[x][y][iz] = 1 end end end end end -- assumes you give it a bitmap of type face util.bitmap4x4_expand_face = function( bitmap4x4 ) --find face local ix local iy local iz local dimension for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then ix = x iy = y iz = z end end end end if( (ix == 0) or (ix == 3) ) then dimension = 'x' end if( (iy == 0) or (iy == 3) ) then dimension = 'y' end if( (iz == 0) or (iz == 3) ) then dimension = 'z' end if( dimension == 'x' ) then for z=0, 3, 1 do for y=0, 3, 1 do bitmap4x4[ix][y][z] = 1 end end end if( dimension == 'y' ) then for x=0, 3, 1 do for z=0, 3, 1 do bitmap4x4[x][iy][z] = 1 end end end if( dimension == 'z' ) then for x=0, 3, 1 do for y=0, 3, 1 do bitmap4x4[x][y][iz] = 1 end end end end util.bitmap4x4_expand_normal = function( bitmap4x4, normal ) --find dimension of normal that isn't 0 local dimension = "" if( normal.x ~= 0 ) then dimension = 'x' end if( normal.y ~= 0 ) then dimension = 'y' end if( normal.z ~= 0 ) then dimension = 'z' end -- find positions that are 1 and set all positions across the normal to 1 for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then if( dimension == 'x' ) then for i=0, 3, 1 do bitmap4x4[i][y][z] = 1 end end if( dimension == 'y' ) then for i=0, 3, 1 do bitmap4x4[x][i][z] = 1 end end if( dimension == 'z' ) then for i=0, 3, 1 do bitmap4x4[x][y][i] = 1 end end end end end end end util.bitmap4x4_expand_edge = function( bitmap4x4 ) local print_string = "" for i=0, 3, 1 do for ii=0, 3, 1 do for iii=0, 3, 1 do print_string = print_string..bitmap4x4[i][ii][iii] end end end minetest.log( "warning", print_string ) --find index dimension not on the edge local ix local iy local iz local dimension for x=0, 3, 1 do for y=0, 3, 1 do for z=0, 3, 1 do if( bitmap4x4[x][y][z] == 1 ) then ix = x iy = y iz = z end end end end if( (ix ~= 0) and (ix ~= 3) ) then dimension = 'x' end if( (iy ~= 0) and (iy ~= 3) ) then dimension = 'y' end if( (iz ~= 0) and (iz ~= 3) ) then dimension = 'z' end if( dimension == 'x' ) then for i=0, 3, 1 do bitmap4x4[i][iy][iz] = 1 end end if( dimension == 'y' ) then for i=0, 3, 1 do bitmap4x4[ix][i][iz] = 1 end end if( dimension == 'z' ) then for i=0, 3, 1 do bitmap4x4[ix][iy][i] = 1 end end print_string = "" for i=0, 3, 1 do for ii=0, 3, 1 do for iii=0, 3, 1 do print_string = print_string..bitmap4x4[i][ii][iii] end end end minetest.log( "warning", print_string ) end util.integer_to_bitmap = function( integer ) local bitmap = { [0] = nil, [7] = nil } local value = 128 for i = 7, 0, -1 do if(integer >= value) then bitmap[i] = 1 integer = integer - value else bitmap[i] = 0 end value = value/2 end return bitmap end util.bitmap_to_integer = function( bitmap ) local integer = 0 local value = 1 for index = 0, 7, 1 do integer = integer + (bitmap[index] * value) value = value * 2 end return integer end --TODO delete this if not used util.mirror_bitmap_across_y = function( bitmap ) local new_array = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 local my = max_index for iy = 0, max_index, 1 do for ix = 0, max_index, 1 do for iz = 0, max_index, 1 do new_array[ix][my][iz] = bitmap[ ix + (iy*2) + (iz*4) ] end end my = my - 1 end return util.array3d_to_bitmap( new_array ) end --bitmap rotation: rotation of the 3d array that represents the bitmap --rotates the array clockwise by 90 degress around the given axis util.rotate_bitmap_around_plus_y = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[iz][iy][max_index-ix] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end util.rotate_bitmap_around_minus_y = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[max_index-iz][iy][ix] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end util.rotate_bitmap_around_plus_z = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[max_index-iy][ix][iz] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end util.rotate_bitmap_around_minus_z = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[iy][max_index-ix][iz] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end util.rotate_bitmap_around_plus_x = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[ix][max_index-iz][iy] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end util.rotate_bitmap_around_minus_x = function( bitmap ) local new_bitmap = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do new_bitmap[ix][iz][max_index-iy] = bitmap[ ix + (iy*2) + (iz*4) ] end end end return util.array3d_to_bitmap( new_bitmap ) end -- bitmap orientation assumes the current bitmap orientation is plus y util.orient_bitmap_towards_plus_z = function( bitmap ) return util.rotate_bitmap_around_plus_x( bitmap ) end util.orient_bitmap_towards_minus_z = function( bitmap ) return util.rotate_bitmap_around_minus_x( bitmap ) end util.orient_bitmap_towards_plus_x = function( bitmap ) return util.rotate_bitmap_around_minus_z( bitmap ) end util.orient_bitmap_towards_minus_x = function( bitmap ) return util.rotate_bitmap_around_plus_z( bitmap ) end util.orient_bitmap_towards_minus_y = function( bitmap ) return util.rotate_bitmap_around_plus_z( util.rotate_bitmap_around_plus_z( bitmap ) ) end util.bitmap_to_array3d = function( bitmap ) local array = { [0] = { [0]={}, [1]={}}, [1]={[0]={}, [1]={}} } local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do array[ix][iy][iz] = bitmap[ ix + (iy*2) + (iz*4)] end end end return array end util.array3d_to_bitmap = function( array ) local bitmap = {} local max_index = 1 for ix = 0, max_index, 1 do for iy = 0, max_index, 1 do for iz = 0, max_index, 1 do bitmap[ ix + (iy*2) + (iz*4) ] = array[ix][iy][iz] end end end return bitmap end