#!/usr/bin/perl -w
# ### BOILERPLATE ###
# Orthographic Cube Firmware
# Copyright (C) 2006 Peter Todd <pete@petertodd.org>
# 
# This program 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.
# 
# This program 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 this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# ### BOILERPLATE ###

# Create the x,y,z vertex rotation table. 

# This takes a x,y,z vertex and rotates it about the x axis and the y axis. No rotation is done for the z axis.

# Some observations... Since this is a cube, x,y,z are either +l or -l where h
# is the length of any side of the cube. So we map + to 1 and - to 0

# The rotations, a and b, are stored as 0 - $p representing 0 to 2pi

# The equations to obtain x,y,z given a,b are as follows:
#
# x = x(cos a) + y(sin a)(sin b) + z(sin a)(cos b)
# y = y(cos b) - z(sin b)
# z = -x(sin a) + y(cos a)(sin b) + z(cos a)(cos b)

# Observe that each of the three parts can be represented as the sum of k(cos i)(cos j),
# therefore our actual lookup table will be in the that form. The lookups will
# then simply substitute cos(90 + x) where sin's are needed.

$dsize = 35;

$l = 8;

$r = 64;
$p = $r / 2;
$pi = 3.1415926532;

$cs = 256/4;

$m = 16;

print "#define proj_lookup_tbl(k,i,j) (proj_lookup_tbl_real[(((k) * ($r * $r)) + ((i) * $r)) + (j)])\n"; 

print "// The following takes k,i,j and returns k(cos i)(cos j)\n";
print "#define ccterm(k,i,j) ((uint16_t)proj_lookup_tbl(((uint8_t)(k)),((uint8_t)(i)) >> 2,((uint8_t)(j)) >> 2))\n";
print "\n";
print "// The following takes vertex x,y,z and angles a,b and returns the rotated x,y or z\n";
print "\n";
print "// x = x(cos a)        + y(sin a)(sin b)           + z(sin a)(cos b)\n";
print "//   = x(cos a)(cos 0) + y(cos a + 90)(cos b + 90) + z(cos a + 90)(cos b)\n";
print "#define proj_lookup_x(x,y,z,a,b) (uint8_t)(((ccterm(x,a,0) + ccterm(y,a + $cs,b + $cs) + ccterm(z,a + $cs,b)) / $m) + ($dsize / 2))\n";
print "\n";
print "// y = y(cos b)        - z(sin b)\n";
print "//   = y(cos 0)(cos b) - z(cos 0)(cos b + 90)\n";
print "#define proj_lookup_y(x,y,z,a,b) (uint8_t)(((ccterm(y,0,b) - ccterm(z,0,b + $cs)) / $m) + ($dsize / 2))\n";
print "\n";
print "// z = -x(sin a)             + y(cos a)(sin b)      + z(cos a)(cos b)\n";
print "//   = -x(cos a + 90)(cos 0) + y(cos a)(cos b + 90) + z(cos a)(cos b)\n";
print "#define proj_lookup_z(x,y,z,a,b) (uint8_t)(((ccterm(-x,a + $cs,0) + ccterm(y,a,b + $cs) + ccterm(z,a,b)) / $m) + ($dsize / 2))\n";
print "\n";

sub round {
	my($number) = shift;
	return int($number + .5 * ($number <=> 0));;
}

# create the lookup table
#
# outer loop is the constant
$thigh = $tlow = 0;
print "const int8_t proj_lookup_tbl_real[] = {\n";
for ($k = 0; $k < 2; $k++){
	print " // k = $k\n";
	# inner loops are the two angles
	for ($i = 0; $i < $r; $i++){
		print "		";
		for ($j = 0; $j < $r; $j++){
			$d = (($k - 0.5) * 2) * $l * cos(($i / $r) * $pi * 2) * cos(($j / $r) * $pi * 2);
			$d = $d * $m;
			
			# report on the extremes of the table
			if ($d > $thigh) { $thigh = $d; }
			if ($d < $tlow) { $tlow = $d; }
		
			# hard limit to -128 to 127
			if ($d < -128) { $d = -128; }
			if ($d > 127) { $d = 127; }
			
			$d = round($d); 

			print "$d";
			if ($j != ($r - 1)){
				print ",";
			}
		}
		print "";
		if ($i != ($r - 1)){
			print ",";
		}
		print " // i = $i \n";
	}
	print "";
	if ($k != 1){
		print ",";
	} 
	print " // k = $k \n";

}

print "}; // highest value = $thigh lowest value = $tlow (before limiting to -128 to 127)\n";
