1. Help with Pointers

Hi all, I am bit confused on how to wrap this pointer. I tried using chatGPT to help, but every time it tried to help, nothing worked. So I'm trying here.

C example being ported to Eu [https://github.com/ColleagueRiley/RGFW/blob/main/examples/gears/gears.c]

//From gl.h 
WINGDIAPI void APIENTRY glLightiv(GLenum light,GLenum pname,const GLint *params); 

--From opengl32 DLL 
public constant xglLightfv = define_c_proc(gl,"+glLightfv",{C_INT,C_INT,C_POINTER}) 
 
public procedure glLightfv(atom light,atom pname,object param) 
	c_proc(xglLightfv,{light,pname,param})  --There's gotta be a better way to wrap this? 
end procedure 
 
--Update, chatGPT recommend this 
 
public constant xglLightfv = define_c_proc(gl, "+glLightfv", {C_INT, C_INT, C_POINTER}) 
 
public procedure glLightfv(atom light,atom pname,object param) 
	atom p = allocate_data(sizeof(param)) 
	 
	c_proc(xglLightfv,{light,pname,p}) 
	 
	free(p) 
end procedure 
include std/ffi.e 
include std/machine.e 
include std/math.e 
include rgfw.e 
include opengl.e 
 
public constant M_PI = 3.14159265 
 
public constant NOP = 0 
public constant EXIT = 1 
public constant DRAW = 2 
 
atom win = NULL 
 
atom view_rotx = 20.0, 
     view_roty = 30.0, 
     view_rotz = 0.0 
    
atom gear1=NULL,gear2=NULL,gear3=NULL 
atom gangle = 0.0 
 
atom fullscreen = GL_FALSE 
atom stereo = GL_FALSE 
atom samples = 0 
atom animate = GL_TRUE 
atom eyesep = 5.0 
atom fix_point = 40.0 
atom left=NULL,right=NULL,asp=NULL 
 
procedure gear(atom inner_radius, atom outer_radius, atom width, atom teeth, atom tooth_depth) 
    atom i, r0, r1, r2, angle, da, u, v, len 
     
    r0 = inner_radius 
    r1 = outer_radius - tooth_depth / 2.0 
    r2 = outer_radius + tooth_depth / 2.0 
    da = 2.0 * M_PI / teeth / 4.0 
     
    glShadeModel(GL_FLAT) 
    glNormal3f(0.0, 0.0, 1.0) 
     
    -- Draw front face 
    glBegin(GL_QUAD_STRIP) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) 
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5) 
    end for 
    glEnd() 
     
    -- Draw front sides of teeth 
    glBegin(GL_QUADS) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) 
        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5) 
        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5) 
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5) 
    end for 
    glEnd() 
     
    glNormal3f(0.0, 0.0, -1.0) 
     
    -- Draw back face 
    glBegin(GL_QUAD_STRIP) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) 
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5) 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) 
    end for 
    glEnd() 
     
    -- Draw back sides of teeth 
    glBegin(GL_QUADS) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5) 
        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5) 
        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5) 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) 
    end for 
    glEnd() 
     
    -- Draw outward faces of teeth 
    glBegin(GL_QUAD_STRIP) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) 
        glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) 
        u = r2 * cos(angle + da) - r1 * cos(angle) 
        v = r2 * sin(angle + da) - r1 * sin(angle) 
        len = sqrt(u * u + v * v) 
        u /= len 
        v /= len 
        glNormal3f(v, -u, 0.0) 
        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5) 
        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5) 
    end for 
    glEnd() 
     
    -- Draw inside radius cylinder 
    glBegin(GL_QUAD_STRIP) 
    for j = 0 to teeth - 1 do 
        angle = j * 2.0 * M_PI / teeth 
        glNormal3f(-cos(angle), -sin(angle), 0.0) 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) 
        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) 
    end for 
    glEnd() 
end procedure 
 
procedure draw() 
	glClear(or_all({GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT})) 
	 
	glPushMatrix() 
	glRotatef(view_rotx,1.0,0.0,0.0) 
	glRotatef(view_roty,0.0,1.0,0.0) 
	glRotatef(view_rotz,0.0,0.0,1.0) 
	 
	glPushMatrix() 
	glTranslatef(-30.0,-2.0,0.0) 
	glRotatef(gangle,0.0,0.0,1.0) 
	glCallList(gear1) 
	glPopMatrix() 
	 
	glPushMatrix() 
	glTranslatef(3.1,-2.0,0.0) 
	glRotatef(-2.0 * gangle - 9.0,0.0,0.0,1.0) 
	glCallList(gear2) 
	glPopMatrix() 
	 
	glPushMatrix() 
	glTranslatef(-3.1,4.2,0.0) 
	glRotatef(-2.0 * gangle - 25.0,0.0,0.0,1.0) 
	glCallList(gear3) 
	glPopMatrix() 
	 
	glPopMatrix() 
end procedure 
 
procedure draw_gears() 
	if stereo then 
		glDrawBuffer(GL_BACK_LEFT) 
		 
		glMatrixMode(GL_PROJECTION) 
		glLoadIdentity() 
		glFrustum(left,right,-asp,asp,5.0,60.0) 
		 
		glMatrixMode(GL_MODELVIEW) 
		 
		glPushMatrix() 
		glTranslated(+0.5 * eyesep,0.0,0.0) 
		draw() 
		glPopMatrix() 
		 
		glDrawBuffer(GL_BACK_RIGHT) 
		 
		glMatrixMode(GL_PROJECTION) 
		glLoadIdentity() 
		glFrustum(-right,-left,-asp,asp,5.0,60.0) 
		 
		glMatrixMode(GL_MODELVIEW) 
		 
		glPushMatrix() 
		glTranslated(-0.5 * eyesep,0.0,0.0) 
		draw() 
		glPopMatrix() 
		else 
			draw() 
	end if 
end procedure 
 
procedure draw_frame() 
	atom frames = 0 
	atom rot0 = -1.0, rate0 = -1.0 
	atom dt, t = time() 
	 
	if rot0 < 0.0 then 
		rot0 = t 
		dt = t - rot0 
		rot0 = t 
	end if 
	 
	if animate then 
		gangle += 70.0 * dt 
		if gangle > 3600.0 then 
			gangle -= 3600.0 
		end if 
	end if 
	 
	draw_gears() 
	 
	RGFW_window_swapBuffers(win) 
	 
	frames += 1 
	 
	if rate0 < 0.0 then 
		rate0 = t 
		if t - rate0 >= 5.0 then 
			atom secs = t - rate0 
			atom fps = frames / secs 
			printf(1,"%d frames",{frames}) 
			rate0 = t 
			frames = 0 
		end if 
	end if 
end procedure 
 
procedure reshape(atom width,atom height) 
	glViewport(0,0,width,height) 
	 
	if stereo then 
		atom w 
		asp = height / width 
		w = fix_point * (1.0 / 5.0) 
		 
		left = -5.0 * ((w - 0.5 * eyesep) / fix_point) 
		right = 5.0 * ((w + 0.5 * eyesep) / fix_point) 
		else 
		atom h = height / width 
		glMatrixMode(GL_PROJECTION) 
		glLoadIdentity() 
		glFrustum(-1.0,1.0,-h,h,5.0,60.0) 
	end if 
	 
	glMatrixMode(GL_MODELVIEW) 
	glLoadIdentity() 
	glTranslatef(0.0,0.0,-40.0) 
end procedure 
 
procedure init() 
 
sequence pos = {5.0,5.0,10.0,0.0} 
sequence red = {0.8,0.1,0.0,1.0} 
sequence green = {0.0,0.8,0.2,1.0} 
sequence blue = {0.2,0.2,1.0,1.0} 
 
glLightfv(GL_LIGHT0,GL_POSITION,pos[4]) --causes program to crash 
glEnable(GL_CULL_FACE) 
glEnable(GL_LIGHTING) 
glEnable(GL_LIGHT0) 
glEnable(GL_DEPTH_TEST) 
 
gear1 = glGenLists(1) 
glNewList(gear1,GL_COMPILE) 
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,{red[1],red[2],red[3],red[4]}) --same as above 
gear(1.0,4.0,1.0,20,0.7) 
glEndList() 
 
gear2 = glGenLists(1) 
glNewList(gear2,GL_COMPILE) 
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,{green[1],green[2],green[3],green[4]}) --same as above 
gear(0.5,2.0,2.0,10,0.7) 
glEndList() 
 
gear3 = glGenLists(1) 
glNewList(gear3,GL_COMPILE) 
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,{blue[1],blue[2],blue[3],blue[4]}) --same as above 
gear(1.3,2.0,0.5,10,0.7) 
glEndList() 
 
glEnable(GL_NORMALIZE) 
end procedure 
 
atom winWidth = 300, winHeight = 300 
atom x = 0, y = 0 
atom flag = 0 
 
--if fullscreen then 
--	flag = RGFW_winodwFullscreen 
--end if 
 
win = RGFW_createWindow("gear",{x,y,winWidth,winHeight},RGFW_windowCenter) 
RGFW_window_makeCurrent(win) 
init() 
 
while not RGFW_window_shouldClose(win) do 
	while RGFW_window_checkEvent(win) do 
		if win = RGFW_quit then 
			exit 
		end if 
		if RGFW_isPressed(win,RGFW_escape) then 
			exit 
		end if 
		if RGFW_isPressed(win,RGFW_left) then 
			view_roty += 5.0 
		end if 
	end while 
	draw_frame() 
end while 
 
glDeleteLists(gear1,1) 
glDeleteLists(gear2,1) 
glDeleteLists(gear3,1) 
 
RGFW_window_close(win) 
 
new topic     » topic index » view message » categorize

2. Re: Help with Pointers

I take it you haven't looked at the glLight() routine that comes with Phix in demo\pGUI\opengl.e, so here are the relevant bits:

-- (not that I can guarantee this works in all cases...) 
xglLightf               = define_c_proc(opengl32,"glLightf",{C_UINT,C_UINT,C_FLOAT}), 
xglLightfv              = define_c_proc(opengl32,"glLightfv",{C_INT,C_INT,C_PTR}), 
 
procedure gl_pokef32(atom dest, sequence data) 
    for i=1 to length(data) do 
        poke(dest,atom_to_float32(data[i])) 
        dest += 4 
    end for 
end procedure 
 
constant gl_vector_buffer = allocate(128) 
 
global procedure glLight(integer light, integer pname, object params) 
    if atom(params) then 
        c_proc(xglLightf,{light,pname,params}) 
    else 
        gl_pokef32(gl_vector_buffer,params) 
        c_proc(xglLightfv,{light,pname,gl_vector_buffer}) 
    end if 
end procedure 

ChatGPT was allocating a buffer but leaving it with whatever garbage was in it.
You should probably also be asking ChatGPT to make things OpenGL ES 2.0 compatible,
since that at least stands a slim chance of running in a web browser or Android/iOS,
whereas 1.1 aka the fixed function pipeline quite definitely does not.

Then again, I thought about converting this very program to ES 2.0 manually several
years ago, but shelved it, and am quietly patting myself on the back now that I've
seen what ChatGPT has output, so that may well be a step too far..

new topic     » goto parent     » topic index » view message » categorize

3. Re: Help with Pointers

Icy_Viking said...

C example being ported to Eu [https://github.com/ColleagueRiley/RGFW/blob/main/examples/gears/gears.c]

//From gl.h 
WINGDIAPI void APIENTRY glLightiv(GLenum light,GLenum pname,const GLint *params); 

OpenGL functions follow a predictable nomenclature:

OpenGL said...

Function type suffixes are typically defined in the following pattern:

FunctionName{1234}{b s i i64 f d ub us ui ui64}{v} 

The first set of braces is an optional number from 1 to 4. This defines the number of parameters of those types that the function takes.

The second set of braces defines the types themselves, as defined by the table to the left.

If the optional v​ suffix is provided, this means the function takes a "vector": a pointer to an array of some number of values.

The function glLightiv takes a vector (a pointer to an array) of GLint values. Sometimes, however, the number of values in the array varies based on some parameter.

In the case of glLight, you have to consult the options for the pname parameter to determine how many values you actually need to provide in the params array.

OpenGL said...

The ten light parameters are as follows:

  • GL_AMBIENT - four integer or floating-point values
  • GL_DIFFUSE - four integer or floating-point values
  • GL_SPECULAR - four integer or floating-point values
  • GL_POSITION - four integer or floating-point values
  • GL_SPOT_DIRECTION - three integer or floating-point values
  • GL_SPOT_EXPONENT - a single integer or floating-point value
  • GL_SPOT_CUTOFF - a single integer or floating-point value
  • GL_CONSTANT_ATTENUATION - a single integer or floating-point value
  • GL_LINEAR_ATTENUATION - a single integer or floating-point value
  • GL_QUADRATIC_ATTENUATION - a single integer or floating-point value

I would say that technically all you have to do is feed it any number of integers and assume they line up.

public procedure glLightiv(integer light, integer pname, sequence params) 
 
    atom pparams = allocate_data(sizeof(C_INT) * length(params)) 
    poke4(pparams, params) 
 
    c_proc(_glLightiv, {light,pname,pparams}) 
 
    free(pparams) 
 
end procedure 

Given the max seems to be four values, you could just "round up" by padding the remaining values first.

public procedure glLightiv(integer light, integer pname, sequence params) 
 
    if length(params) < 4 then 
        params &= repeat(0, 4-length(params)) 
    end if 
 
    atom pparams = allocate_data(sizeof(C_INT) * length(params)) 
    poke4(pparams, params) 
 
    c_proc(_glLightiv, {light,pname,pparams}) 
 
    free(pparams) 
 
end procedure 

But to be safe, you should check the length of params corresponds to the provided pname value.

public procedure glLightiv(integer light, integer pname, sequence params) 
 
    integer required = 0 
 
    switch pname do 
        case GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION then 
            required = 4 
        case GL_SPOT_DIRECTION then 
            required = 3 
        case GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION, 
            GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION then 
            required = 1 
    end switch 
 
    if required != length(params) then 
        error:crash("expected %d params but received %d", {required,length(params)}) 
    end if 
 
    atom pparams = allocate_data(sizeof(C_INT) * length(params)) 
    poke4(pparams, params) 
 
    c_proc(_glLightiv, {light,pname,pparams}) 
 
    free(pparams) 
 
end procedure 

-Greg

new topic     » goto parent     » topic index » view message » categorize

4. Re: Help with Pointers

From the perspective of Euphoria/Phix, glLightfv/poke(atom_to_float32()) should handle all the cases needed, or I
suppose you could check whether params is all int and if so use glLightiv/poke4. Just don't mix f/poke4 or i/to_f32.

I am in no position to say whether iv might produce grubbier/grainier results than fv, or vice-versa.
Should the results always be indistinguishable, then iv would be a (likely-non-measurable) smidge faster.

Otherwise, of course, totally agree with everything Greg said, except the potential iv/fv mixup (as existed in the OP).

new topic     » goto parent     » topic index » view message » categorize

5. Re: Help with Pointers

Thanks Greg. You've been a great help as always.

Here is the openGL wrapper I've been working on. Its mainly complete. Might be a little rough around the edges, but works for the most part.

I'll post my RGFW wrapper a bit later.

You'll need to use the 64-bit version of Euphoria for this to work.

[https://github.com/gAndy50/Misc/blob/master/GL/openGL.e]

new topic     » goto parent     » topic index » view message » categorize

6. Re: Help with Pointers

Icy_Viking said...

Thanks Greg. You've been a great help as always.

Mr Invisible here deserves a mention too...

new topic     » goto parent     » topic index » view message » categorize

7. Re: Help with Pointers

petelomax said...

From the perspective of Euphoria/Phix, glLightfv/poke(atom_to_float32()) should handle all the cases needed, or I
suppose you could check whether params is all int and if so use glLightiv/poke4. Just don't mix f/poke4 or i/to_f32.

I am in no position to say whether iv might produce grubbier/grainier results than fv, or vice-versa.
Should the results always be indistinguishable, then iv would be a (likely-non-measurable) smidge faster.

Otherwise, of course, totally agree with everything Greg said, except the potential iv/fv mixup (as existed in the OP).

On a side note, I find myself having to write peek/poke float routines over and over again, so I'm planning to add them directly to std/machine.e. Not sure why we didn't add them with peek_pointer(), etc.

petelomax said...

Mr Invisible here deserves a mention too...

I appreciate your contributions, Pete!

-Greg

new topic     » goto parent     » topic index » view message » categorize

8. Re: Help with Pointers

ghaberek said...
petelomax said...

From the perspective of Euphoria/Phix, glLightfv/poke(atom_to_float32()) should handle all the cases needed, or I
suppose you could check whether params is all int and if so use glLightiv/poke4. Just don't mix f/poke4 or i/to_f32.

I am in no position to say whether iv might produce grubbier/grainier results than fv, or vice-versa.
Should the results always be indistinguishable, then iv would be a (likely-non-measurable) smidge faster.

Otherwise, of course, totally agree with everything Greg said, except the potential iv/fv mixup (as existed in the OP).

On a side note, I find myself having to write peek/poke float routines over and over again, so I'm planning to add them directly to std/machine.e. Not sure why we didn't add them with peek_pointer(), etc.

petelomax said...

Mr Invisible here deserves a mention too...

I appreciate your contributions, Pete!

-Greg

Thanks Pete, you've been helpful too. That's great to hear Greg. Having those functions will be handy!

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu