Oxygen Basic
Programming => Example Code => Graphics => Topic started by: Frankolinox on February 01, 2014, 01:58:31 AM
-
this was a hard job.. I can say only.. looks so simple but it wasn't easy..
the example works, but there were some hurdles to take to make it run. here some more question:
a) qt: why a "declare function... lib... alias..." doesn't work in "openGL window frame" but with no problem in win api frame (like menu example)? I've got immediately an error message
b) what advantage I have with
% ExplicitMain
in top of code example ? some openGL example use it (newer and complexer ones) other use it not
c) if you like to test the example take attention. I have modified "openGLwindowfram.inc" with menu features..place this example in "example/openGL" folder.
'
' openGL exercise: cube textured, gridlines, sphere
' a way how to insert a menu in openGL 31.01.2014 by frankolinox
'
includepath "$\inc\"
$ FileName "openGL_scene+Menu_go.exe"
'include "RTL32.inc"
'include "RTL64.inc"
''include "minwin.inc"
$ title "Crates, sphere + gridlines"
''% ExplicitMain
include "OpenglSceneFrame.inc"
includepath ""
include "shapes.inc"
include "particles.inc"
include "materials.inc"
' error: doesn't accept declare statements in openGL
'--------------------------------------------------------------------- //
''DECLARE FUNCTION CreateMenu LIB "USER32.DLL" ALIAS "CreateMenu" ( _
'' ) AS LONG
''DECLARE FUNCTION GetMenu LIB "USER32.DLL" ALIAS "GetMenu" ( _
'' BYVAL hWnd AS LONG _
'' ) AS LONG
'--------------------------------------------------------------------- //
' error: doesn't accept declare statements in openGL
indexbase 1
sys texn[3]
sys GdiplusToken
sys cube,sphere,helix,tors
float ang1
float li[16]
float ma[13]
sys cube pent
RECT crect
materials WhiteMaterial,RedMaterial
sub initialize(sys hWnd)
========================
'
'GDIPLUS
'
sys hr
GdiplusStartupInput StartupInput
StartupInput.GdiplusVersion = 1
hr=GdiplusStartup GdiplusToken, StartupInput, null
'
if hr then
print "Error initializing GDIplus: " hex hr
exit function
end if
'
'PREPARE TEXTURES
'
glGenTextures 2, texn
'
static sys res=256
string imgs[1]=""
''GetTexImage "../images/crate.jpg",res,imgs[1]
GetTexImage "townColor.jpg",res,imgs[1] ''townColor.jpg
MakeTexture *imgs[1],res,res,texn[1]
'
sphere=CompileList : Spheric 0.5,0.5,6 : glEndList '1,1,6 : glEndList
cube=CompileList : CubeForm : glEndList
pent=CompileList : Sides 5,1,1 : glEndList
'
'standard lighting
------------------
li<=
0.0, 8.0, 8.0, 1.0, 'position
1.0, 1.0, 1.0, 1.0, 'ambient
1.0, 1.0, 1.0, 1.0, 'diffuse
1.0, 1.0, 1.0, 1.0 'specular
'standard material
------------------
ma<=
.15, .15, 0.2, 1.0, 'ambient
0.7, 0.7, 0.6, 1.0, 'diffuse
0.0, 0.0, 0.1, 1.0, 'specular
0 'shininess
Material ma
Lighting li
'
' below doesn't work at all ------------------ //
WhiteMaterial.standard
RedMaterial.standard
RedMaterial.ambient <= .15,.0,.0,1.
RedMaterial.diffuse <= .65,.0,.0,1.
' above doesn't work at all ------------------ //
SetTimer hWnd,1,10,null
end sub
sub Release(sys hwnd)
'====================
glDeleteLists cube,1
glDeleteLists pent,1
glDeleteTextures 2, texn
GdiplusShutdown GdiplusToken
killTimer hwnd, 1
end sub
sub RenderCrate(float x,y,z,sc,sys tex)
=======================================
'glColor4f .99,.99,.99,.99
glEnable GL_TEXTURE_2D
glBindTexture GL_TEXTURE_2D,tex
glPushMatrix
gltranslatef x,y+0.35,z-1
glrotatef ang1,0,1,0
glscalef sc,sc,sc
glCallList Cube
'glCallList Pent
glPopMatrix
glDisable GL_TEXTURE_2D
end sub
sub scene(sys hWnd)
'==================
'
'Ctrl-P take snapshot
'
sys i,j
static sys photo
if key[80] and key[17] and photo=0
TakeOpenglSnapShot hwnd,"tim50.jpg","image/jpeg",50
photo=1
elseif key[80]=0
photo=0
end if
static single ra,ri,angi1=.5
'
glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
glEnable GL_DEPTH_TEST
glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
glEnable GL_BLEND
glLoadIdentity
'
glClearColor 0.5, 0.5, 0.7, 0
'
'
float fcolor[4]={.5, .5, .7, .99}
glfogi GL_FOG_MODE,GL_EXP
glfogf GL_FOG_DENSITY,0.1
glfogfv GL_FOG_COLOR, fcolor
glfogf GL_FOG_INDEX, 0
glfogf GL_FOG_START, -1.0
glfogf GL_FOG_END, -100.0
glEnable GL_FOG
'
glEnable GL_LIGHTING
glEnable GL_NORMALIZE
glColor4f .99,.99,.99,.99
sys n=texn[1]
RenderCrate 11.5,-0.9,-24.0,0.5,n
RenderCrate 6.5,-0.9,-16.0,0.5,n
RenderCrate 2.5,-0.9,-8.0, 0.5,n
RenderCrate 0.5,-0.9,-4.0, 0.5,n
RenderCrate -0.5,-0.9,-2.0, 0.5,n
'
' sphere ----------------------
glLoadIdentity
glPushMatrix
glTranslatef -3.,1.,-7.0
RedMaterial.act
glScalef 2.,2.,2.
glEnable GL_LIGHTING
glCallList sphere
glDisable GL_LIGHTING
WhiteMaterial.act
glPopMatrix
'
' - gridlines ----------------- //
glLoadIdentity
glrotatef ang1,0,1,0
GLBegin GL_LINES
GLColor3f 0,0,255 '0,255,0
For i = -10 To 10
For j = -10 To 10
glVertex3f -10, -1, j
glVertex3f 10, -1, j
glVertex3f i, -1, -10
glVertex3f i, -1, 10
Next
Next
GLEnd
'
ang1+=angi1
if ang1>360 then ang1-=360
'
sleep 10
end sub
''MainWindows width,height,WS_OVERLAPPEDWINDOW
MainWindows 860,640,WS_OVERLAPPEDWINDOW
'' -------------------------------------------- //
Function MainWindows(sys width,height,style)
===========================================
'
sys a,b,c,hWnd
WNDCLASS wc
MSG wm
'
inst=GetModuleHandle 0
'
with wc. '
style=CS_HREDRAW or CS_VREDRAW
lpfnWndProc = @wndprocs
cbClsExtra = 0
cbWndExtra = 0
hInstance = inst
hIcon = LoadIcon 0, IDI_APPLICATION
hCursor = LoadCursor 0,IDC_ARROW
hbrBackground = GetStockObject WHITE_BRUSH '
lpszMenuName = 0
lpszClassName = strptr "wins"
end with
if not RegisterClass @wc
MessageBox 0,"Registration failed","Problem",MB_ICONERROR
exit function
end if
'Create the main window.
hwnd = CreateWindowEx(
0, 'no extended styles
"wins", 'class name
"Main Window", 'window name
style, '
CW_USEDEFAULT, 'default horizontal position
CW_USEDEFAULT, 'default vertical position
100+width, 'default width
100+height, 'default height
null, 'no parent or owner window
null, 'class menu used
inst, 'instance handle
null); 'no window creation data
if not hWnd then
MessageBox 0,"Unable to create window","problem",MB_ICONERROR
exit function
end if
'
sys hMenu,hMenuPopup,hSysMenu
ShowWindow hWnd,SW_NORMAL
UpdateWindow hWnd
'
'MESSAGE LOOP
'============
'
sys bRet
'
while bRet := GetMessage @wm, 0, 0, 0
if bRet == -1 then
'show an error message?
else
#ifdef EscapeKeyEnd
if wm.message=WM_KEYDOWN
if wm.wparam=27
SendMessage hwnd,WM_DESTROY,0,0
end if
end if
#endif
#ifdef RelayMessages
m=wm.message
select m
'
case WM_LBUTTONDBLCLK
=====================
'
SendMessage hwnd,WM_COMMAND,1100-0x200+m, 0
'
case WM_KEYDOWN
===============
'
m=wm.wparam
select m
case VK_RETURN
for i=1 to nchw
if wm.hwnd=hchw(i)
SendMessage hwnd,WM_COMMAND,2000+VK_RETURN,0
if i>1 then continue while 'first window is editor
end if
next
case VK_F1 to VK_F10
SendMessage hwnd,WM_COMMAND,1001+m-VK_F1, 0
case "A" to "Z"
if CtrlKey
SendMessage hwnd,WM_COMMAND,2000+m, 0
if m=65 or m=70 or m=71 then continue while
end if
case VK_ESCAPE
SendMessage hwnd,WM_COMMAND,2200+VK_ESCAPE, 0
Continue do
end select
'
end select
'
#endif
TranslateMessage @wm
DispatchMessage @wm
end if
wend
'
end function ; end of WinMain
'
'---------------
'DEFAULT WNDPROC
'
function WndProcs(sys hwnd, uMsg, wParam, lParam) as long callback
=================================================================
'
'MENU ITEMS
'
%IDM_FILE_NEW 40001
%IDM_FILE_OPEN 40002
%IDM_FILE_SAVE 40003
%IDM_FILE_SAVE_AS 40004
%IDM_APP_EXIT 40005
%IDM_EDIT_UNDO 40006
%IDM_EDIT_CUT 40007
%IDM_EDIT_COPY 40008
%IDM_EDIT_PASTE 40009
%IDM_EDIT_CLEAR 40010
%IDM_APP_HELP 40011
%IDM_APP_ABOUT 40012
static sys hDC,hRC
select umsg
'
case WM_CREATE
PostQuitMessage 0
case WM_COMMAND
case WM_DESTROY
'
PostQuitMessage 0
case WM_KEYDOWN
Select wParam
Case 27 : SendMessage hwnd, WM_CLOSE, 0, 0 'ESCAPE
End Select
case else
'
function=DefWindowProc hWnd,uMsg,wParam,lParam
'
end select
end function
I have fun at all with this example because of three learning hours with win api and openGL and a lot of error messages ;)
all you need, source code, exe + oxygen.dll you find in zip folder.
best regards, frank
.
-
Hi Frank,
Thanks for your hard work!
There is a solution for extending the OpenGLSceneFrame WndProc, which is what you need for adding a set of menus, and any other windows items you require.
I have added a few lines to OpenglSceneFrame to make this possible:
sys WndProcExtra 'callback for customised windows message processing
function WndProc(sys hwnd, uMsg, wParam, lParam) as sys callback
================================================================
'
static sys hDC,hRC
'
if WndProcExtra
if call WndProcExtra(hwnd,uMsg,wParam,lParam) then exit function
end if
Then you can create a procedure in your application, to intercept, and possibly override the standard WndProc message processing
function WindowMessages(sys hwnd, uMsg, wParam, lParam) as sys, link WndProcExtra
...
function WindowMessages(sys hwnd, uMsg, wParam, lParam) as sys, link WndProcExtra
=================================================================================
'MENU ITEMS
'
%IDM_FILE_NEW 40001
%IDM_FILE_OPEN 40002
%IDM_FILE_SAVE 40003
%IDM_FILE_SAVE_AS 40004
%IDM_APP_EXIT 40005
%IDM_EDIT_UNDO 40006
%IDM_EDIT_CUT 40007
%IDM_EDIT_COPY 40008
%IDM_EDIT_PASTE 40009
%IDM_EDIT_CLEAR 40010
%IDM_APP_HELP 40011
%IDM_APP_ABOUT 40012
'
static sys hdc,hMenu,hMenuPopup
static String txt
static rect crect
static PaintStruct Paintst
sys id
'
select case uMsg
'
case WM_CREATE
'
hMenu = CreateMenu
hMenuPopup = CreateMenu
AppendMenu hMenuPopup, MF_STRING, IDM_FILE_NEW, "&New"
AppendMenu hMenuPopup, MF_STRING, IDM_FILE_OPEN, "&Open..."
AppendMenu hMenuPopup, MF_STRING, IDM_FILE_SAVE, "&Save"
AppendMenu hMenuPopup, MF_STRING, IDM_FILE_SAVE_AS, "Save &As..."
AppendMenu hMenuPopup, MF_SEPARATOR, 0, null
AppendMenu hMenuPopup, MF_STRING, IDM_APP_EXIT, "E&xit"
AppendMenu hMenu, MF_POPUP, hMenuPopup, "&File"
hMenuPopup = CreateMenu
AppendMenu hMenuPopup, MF_STRING, IDM_EDIT_UNDO, "&Undo"
AppendMenu hMenuPopup, MF_SEPARATOR, 0, null
AppendMenu hMenuPopup, MF_STRING, IDM_EDIT_CUT, "Cu&t"
AppendMenu hMenuPopup, MF_STRING, IDM_EDIT_COPY, "&Copy"
AppendMenu hMenuPopup, MF_STRING, IDM_EDIT_PASTE, "&Paste"
AppendMenu hMenuPopup, MF_STRING, IDM_EDIT_CLEAR, "De&lete"
AppendMenu hMenu, MF_POPUP, hMenuPopup, "&Edit"
hMenuPopup = CreateMenu
AppendMenu hMenuPopup, MF_STRING, IDM_APP_HELP, "&Help"
AppendMenu hMenuPopup, MF_STRING, IDM_APP_ABOUT, "&About MenuDemo..."
AppendMenu hMenu, MF_POPUP, hMenuPopup, "&Help"
'
SetMenu hwnd, hMenu
SetWindowText hwnd,"Menu Demo"
'
sys dis=MF_DISABLED or MF_GRAYED
CheckMenuItem hMenu,IDM_FILE_NEW, MF_CHECKED
EnableMenuItem hMenu,IDM_FILE_OPEN,dis
case WM_COMMAND
hMenu = GetMenu(hwnd)
if wparam = IDM_APP_EXIT then
SendMessage hwnd, WM_CLOSE, 0, 0
return 1 'indicate this message has been intercepted / no further action
end if
'
case WM_KEYDOWN
select case wparam
keydown 'macro
'default cases
case 27 : return 1 'intercept Esc key: prevent sutdown / take no action
end select
end select
end function
App demo and new OpenglSceneFrame Attached:
.
-
thank you very mucho charles for this good idea :)
my new openGL menu example is now running fine, nice day to the north.
kind regards, frank
.
-
hi charles, do you know a chance or programming technic how to "insert" a sphere in an existing openGL scene by clicking a menu item? do you have a link or an idea if that's possible with oxygen? My idea was to catch a "sphere" by name (string) in wndproc callback part, but how does the "scene" know that's this new sphere is placed in it? the scene has to be rendered in updated modus ? :)
regards, frank
-
Interesting idea, Frank. A right-click pop-up menu could be used to create, or delete picked objects in the scene. To do this, the program needs to maintain an array of objects to be displayed, giving shape, color position etc. The shapes can be pre-compiled glLists.
examples/Opengl/MovObjKeyb.o2bas would a good basis for building such a menu-controlled demo. I will give it some further thought. :)
-
hi charles, if I am using the "MovObjKeyb.o2bas" example as basis (a good one!) how I can setup a
"sphere" class? ;)
thanks, frank
-
here's my first attempt, but I don't know if that's correct..
'
'-------- test: sphere class by frankolinox, 5.2.2014, oxygenbasic
'
includepath "$\inc\"
$ FileName "t.exe"
'include "RTL32.inc"
'include "RTL64.inc"
'
% ExplicitMain
% UsesClasses
$ title "sphere class"
$ fontA "Arial",FW_SEMIBOLD
'
include "OpenglSceneFrame.inc"
'
includepath ""
include "shapes.inc"
indexbase 1
sys texn[16]
sys GdiplusToken
float ang1
float li[16]
float ma[13]
sys cube,pent,sphere,helix,tors
'---------------------- that's ok for sphere class? ----------------- //
============
class sphere
============
float x,y,z
float rw,rh,m 'sphere
sys tex
'
float angx,angy,angz ' I needed that one too?
float xx,yy,zz ' I needed that one too?
method Render()
===============
if tex then glBindTexture GL_TEXTURE_2D,tex
glPushMatrix
gltranslatef x,y,z
glrotatef angx,1,0,0 'rotate yz : pitch
glrotatef angy,0,1,0 'rotate xz : yaw
glrotatef angz,0,0,1 'rotate xy : yaw
glscalef rw,rw,rw 'sc,sc,sc
''ConeFaces n,rz,ry,sm
Spheric rw,rh,m ''1,1,6
glPopMatrix
end method
'
method anchor()
===============
xx=x
yy=y
zz=z
end method
'
method move(single mx,my,mz)
============================
x=xx+mx
y=yy+my
z=zz+mz
limit
end method
'
method limit()
==============
float d=-z,id=-1/z
if x*id<-0.5 then x=-.5*d
if y*id<-0.4 then y=-.4*d
if z>-1.0 then z=-1.0
if x*id>.5 then x=.5*d
if y*id>.4 then y=.4*d
end method
'
method drag()
=============
float dx,dy,dz
dx=mposx-sposx
dy=sposy-mposy
dz=-z/crect.right
move dx*dz,dy*dz,0
end method
'
end class
'---------------------- that's ok for sphere class? ----------------- //
'------------------------------- shapes.inc ------------- //
sub HemiSpheric(float rw, rh, m)
================================
float s,c,r,r1,r2,x1,x2,y1,y2,z1,z2
sys e,i,j,st=m
e=90-st
for j=0 to e step st
r=rad(j) : r1=rw*cos(r) : y1=rh*sin(r)
r=rad(j+st) : r2=rw*cos(r) : y2=rh*sin(r)
glBegin GL_QUAD_STRIP
for i=0 to 360 step st
r=rad(i)
c=cos(r) : s=sin(r)
x1=r1*c : z1=r1*s
x2=r2*c : z2=r2*s
glNormal3f x2, y2, z2
glVertex3f x2, y2, z2
glNormal3f x2, y1, z1
glVertex3f x1, y1, z1
next
glEnd
next
end sub
sub spheric(float rw,rh,m)
==========================
glPushMatrix
hemispheric rw, rh, m
glRotatef 180.0,1,0,0
hemispheric rw, rh, m
glPopMatrix
end sub
'-------------- // test
print "ok"
'--------------- //
' 'sphere=CompileList : Spheric 1,1,6 : glEndList
and step two how to make a sphere data setup (like charles have done for cones) that's not clear here
regards, frank
-
glCompiling
include "shapes.inc"
initialising:
cube=CompileList : CubeForm : glEndList
sphere=CompileList : Spheric 1,1,6 : glEndList
Calling:
'MYSTERIOUS RED PLANET
glPushMatrix
glTranslatef -20.,10.,-95.0
RedMaterial.act
glScalef 6.,6.,6.
glEnable GL_LIGHTING
glCallList sphere
'glDisable GL_LIGHTING
WhiteMaterial.act
glPopMatrix
Releasing:
glDeleteLists cube,1
glDeleteLists sphere,1
Compiled lists are very efficient in Opengl. Once the shape is compiled, it can be used with materials & textures, and scaled to any proprtion.
-
yes, charles, that was basis for my first example above (post 1, post 3) :)
a) I thought as you've mentioned the "pickup and move objects" ("MovObjKeyb.o2bas") oxygen example, that it's better to use "classes" for the primitives, that confused me a little bit. therefore I've started with a "sphere class" setup (my last post), but I was not sure how that's going correct with "sphere data" setup, as you did it with "cone" data setup. I will send a new example and if you have time you can check it :)
b) to pick up objects the method I like so I will follow this example and try to insert primitives in openGL scene by "name" (string) or %sphere equates for example.
regards, frank
-
Hi Frank,
I'm using classes to keep all the variables and functions bunched together. When you have multiple objects with varioust behaviours, it keeps the program manageable.
I've got the menu integrated with MoveObjKeyb. But not doing anything yet.
Still using cones but this is easily abstracted to support other shapes.
progress so far:
.
-
The menu is now functional for selecting materials
Needs this Oxygen.dll update, for some of the OOP:
http://www.oxygenbasic.org/forum/index.php?topic=749.0
.
-
More fun and games:
SceneObject has replaced the Cones class. So you can change shapes from the menu, as well as select materials. If no object has been picked the a new object is created
Using the shift key with the mouse enables movement in the z direction. The ctrl key enables object rotation. The home key sets all rotations to 0 for the selected object.
Make sure you have the latest Oxygen.dll (link above), released yesterday
.
-
thanks charles for these both openGL examples, that's very liked here with right-click material apply :) that's similar what I wanted to create last year but I haven't that big knowledge so far with oxygen and win api at that time.
regards, frank