
--
-- Copyright (C) 2020  <fastrgv@gmail.com>
--
-- 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 3 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 may read the full text of the GNU General Public License
-- at <http://www.gnu.org/licenses/>.
--

with system;
with gl, gl.binding, gl.pointers;
with glu, glu.binding, glu.pointers;
with glext, glext.binding, glext.pointers;

with interfaces.c;
use type interfaces.c.unsigned_short;


with ada.finalization;
with unchecked_deallocation;

with text_io;  use text_io;
with ada.numerics.generic_elementary_functions;

with matutils;
use matutils;


package body spherex is --unitSphere, no texture, no normals



	package fmath is new
			Ada.Numerics.generic_elementary_functions( float );
	use fmath;



procedure initialize( eli: in out eloid ) is
begin
	eli.vert := new varray;
	eli.elem := new earray;
end initialize;

procedure vfree is new unchecked_deallocation(varray,vap);
procedure efree is new unchecked_deallocation(earray,eap);

procedure finalize( eli: in out eloid ) is
begin
	vfree( eli.vert );
	efree( eli.elem );
end finalize;









procedure myassert( condition : boolean;  flag: integer:=0 ) is
begin
  if condition=false then
  		put("ASSERTION Failed!  ");
		if flag /= 0 then
			put_line( "rectxfineobj @ " & integer'image(flag) );
		end if;
		new_line;
  		raise program_error;
  end if;
end myassert;











-- This version assumes Y=Npole
-- maps equirectangular texture (2x1) to a spheroid
-- as you would for NASA earth maps;  the entire top edge
-- maps to the Npole(0,1,0),  bottom->Spole(0,-1,0):
procedure yseteli( eli: eloid ) is

	t, k, ejj, tj : integer := 0;
	jj : glushort := 0;


	x00,y00,z00,
	x01,y01,z01,
	x10,y10,z10,
	x11,y11,z11,
	u0,u1,v0,v1 : float;

	onepi : constant float := ada.numerics.pi;
	twopi : constant float := ada.numerics.pi * 2.0;
	fsides:   constant float := float(nsides);
	fradials: constant float := float(nradials);

-- theta = U in [0, twopi]
-- phi   = V in [0, onepi]
--
-- theta = arctan(y,x)
-- phi = arccos(z)
--
-- x = sin(phi) cos(theta)
-- z = sin(phi) sin(theta)
-- y = cos(phi)
--
-- NOTE:  the normal vector at a point (x0,y0,z0) on the
-- ellipsoid is (x0, y0, z0) !!!


	procedure surfac( theta, phi: float;  x,y,z: out float ) is
		norm: float;
	begin
		x:=fmath.sin(phi)*fmath.cos(theta);
		z:=fmath.sin(phi)*fmath.sin(theta);
		y:=fmath.cos(phi);
	end surfac;


begin


	for slice in 1..nradials loop -- U theta in 0..2pi

		u0:=float(slice-1)/fradials;
		u1:=float(slice-0)/fradials;

		for side in 1..nsides loop -- V phi in 0..pi
			v0:=float(side-1)/fsides;
			v1:=float(side-0)/fsides;

			surfac(twopi*u0,onepi*v0, x00,y00,z00);
			surfac(twopi*u0,onepi*v1, x01,y01,z01);
			surfac(twopi*u1,onepi*v0, x10,y10,z10);
			surfac(twopi*u1,onepi*v1, x11,y11,z11);


			eli.vert(k+ 1):=x10;  eli.vert(k+ 2):=y10;  eli.vert(k+ 3):=z10; --A
			eli.vert(k+ 4):=x11;  eli.vert(k+ 5):=y11;  eli.vert(k+ 6):=z11; --B
			eli.vert(k+ 7):=x01;  eli.vert(k+ 8):=y01;  eli.vert(k+ 9):=z01; --C
			eli.vert(k+10):=x00;  eli.vert(k+11):=y00;  eli.vert(k+12):=z00; --D

			k:=k+12;


			-- element indices:
			eli.elem(ejj+1):=jj+0;
			eli.elem(ejj+2):=jj+1;
			eli.elem(ejj+3):=jj+2;
			eli.elem(ejj+4):=jj+2;
			eli.elem(ejj+5):=jj+3;
			eli.elem(ejj+6):=jj+0;
			ejj:=ejj+6;
			jj:=jj+4;


		end loop; --side

	end loop; --slice


myassert(k=nvert,1);


end yseteli;














use gl;
use glext;
use glext.binding;
use gl.binding;

procedure draw( eli: eloid; vertbuff, elembuff : gluint ) is
begin

	-- 0th attribute:  vertices
	glBindBuffer(gl_array_buffer, vertbuff);
	glBufferData(gl_array_buffer, glsizeiptr(4*nvert), eli.vert(1)'address, gl_static_draw);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0,3,gl_float,gl_false,0, system.null_address);

	-- element indices:
	glBindBuffer(gl_element_array_buffer, elembuff);
	glBufferData(gl_element_array_buffer, glsizeiptr(2*nelm), eli.elem(1)'address, gl_static_draw);

	glEnable(gl_blend);
	glBlendFunc(gl_src_alpha, gl_one_minus_src_alpha);

	glDrawElements( gl_triangles, glint(nvert), gl_unsigned_short, system.null_address );

	glDisableVertexAttribArray(0);

end draw;







end spherex;

