Here is a very simple example to show you how to create a Visual BBplugin with OpenGL.
'+--------------------------------------------------------------------------+
'| |
'| Woofer |
'| BassBox OpenGL plugin |
'| |
'| Version 1.00 |
'| |
'+--------------------------------------------------------------------------+
'| |
'| Author Patrice TERRIER |
'| |
'| copyright(c) 2007 |
'| |
'| Patrice Terrier http://www.zapsolution.com |
'| |
'+--------------------------------------------------------------------------+
'| Project started on : 10-30-2007 (MM-DD-YYYY) |
'| Last revised : 11-14-2007 (MM-DD-YYYY) |
'+--------------------------------------------------------------------------+
'
#COMPILE DLL "Woofer.dll"
#INCLUDE "Include\BBPlugin.inc"
'//declare sub skDebug lib "SKENGINE.DLL" (byval Msg$)
type RECT
nLeft as long
nTop as long
nRight as long
nBottom as long
end type
macro const = macro
' Key State Masks for Mouse Messages
const MK_LBUTTON = &H0001
const MK_RBUTTON = &H0002
const MK_SHIFT = &H0004
const MK_CONTROL = &H0008
const MK_MBUTTON = &H0010
const MK_XBUTTON1 = &H0020
const MK_XBUTTON2 = &H0040
const WM_MOUSEMOVE = &H200
const WM_LBUTTONDOWN = &H201
const WM_LBUTTONUP = &H202
const WM_LBUTTONDBLCLK = &H203
const WM_RBUTTONDOWN = &H204
const WM_RBUTTONUP = &H205
const WM_RBUTTONDBLCLK = &H206
const WM_MBUTTONDOWN = &H207
const WM_MBUTTONUP = &H208
const WM_MBUTTONDBLCLK = &H209
const WM_MOUSEWHEEL = &H20A
const WM_XBUTTONDOWN = &H20B
const WM_XBUTTONUP = &H20C
const WM_XBUTTONDBLCLK = &H20D
const GL_UNSIGNED_BYTE = &h1401&
const GL_QUADS = &h0007&
const GL_COLOR_BUFFER_BIT = &h4000&
const GL_DEPTH_BUFFER_BIT = &h0100&
const GL_MATRIX_MODE = &h0BA0&
const GL_MODELVIEW = &h1700&
const GL_PROJECTION = &h1701&
const GL_SMOOTH = &h1D01&
const GL_DEPTH_TEST = &h0B71&
const GL_SRC_ALPHA = &h0302&
const GL_ONE = &h0001&
const GL_BLEND = &h0BE2&
const GL_LINEAR = &h2601&
const GL_PERSPECTIVE_CORRECTION_HINT = &h0C50&
const GL_NICEST = &h1102&
const GL_TEXTURE_2D = &h0DE1&
const GL_TEXTURE_MAG_FILTER = &h2800&
const GL_TEXTURE_MIN_FILTER = &h2801&
const GL_LUMINANCE = &h1909&
const GL_RGB = &H1907
const GL_RGBA = &H1908
const GL_TEXTURE = &H1702
const GL_LESS = &H0201
const GL_LIGHTING = &H0B50
const GL_GREATER = &H0204
declare function GetClientRect lib "USER32.DLL" alias "GetClientRect" (byval hwnd as dword, lpRect as RECT) as long
declare function wglGetProcAddress lib "opengl32.dll" alias "wglGetProcAddress" (lpStr as asciiz) as long
declare sub glEnd lib "opengl32.dll" alias "glEnd"
declare sub glPushMatrix lib "opengl32.dll" alias "glPushMatrix"
declare sub glLoadIdentity lib "opengl32.dll" alias "glLoadIdentity"
declare sub glBegin lib "opengl32.dll" alias "glBegin" (byval long)
declare sub glClear lib "opengl32.dll" alias "glClear" (byval dword)
declare sub glEnable lib "opengl32.dll" alias "glEnable" (byval dword)
declare sub glDisable lib "opengl32.dll" alias "glDisable" (byval dword)
declare sub glClearDepth lib "opengl32.dll" alias "glClearDepth" (byval double)
declare sub glShadeModel lib "opengl32.dll" alias "glShadeModel" (byval dword)
declare sub glMatrixMode lib "opengl32.dll" alias "glMatrixMode" (byval dword)
declare sub glHint lib "opengl32.dll" alias "glHint" (byval dword, byval dword)
declare sub glBlendFunc lib "opengl32.dll" alias "glBlendFunc" (byval long, byval long)
declare sub glTexCoord2f lib "opengl32.dll" alias "glTexCoord2f" (byval single, byval single)
declare sub glTexEnvi lib "opengl32.dll" alias "glTexEnvi" (byval dword, byval dword, byval long)
declare sub glVertex3f lib "opengl32.dll" alias "glVertex3f" (byval single, byval single, byval single)
declare sub glTranslatef lib "opengl32.dll" alias "glTranslatef" (byval single, byval single, byval single)
declare sub glColor3f lib "opengl32.dll" alias "glColor3f" (byval single, byval single, byval single)
declare sub glFrustum lib "opengl32.dll" alias "glFrustum" (byval double, byval double, byval double, byval double, byval double, byval double)
declare sub glColor4f lib "opengl32.dll" alias "glColor4f" (byval single, byval single, byval single, byval single)
declare sub glViewport lib "opengl32.dll" alias "glViewport" (byval long, byval long, byval long, byval long)
declare sub glClearColor lib "opengl32.dll" alias "glClearColor" (byval single, byval single, byval single, byval single)
declare sub glGenTextures lib "opengl32.dll" alias "glGenTextures" (byval dword, textures as ANY)
declare sub glBindTexture lib "opengl32.dll" alias "glBindTexture" (byval dword, byval dword)
declare sub glTexParameteri lib "opengl32.dll" alias "glTexParameteri" (byval dword, byval dword, byval long)
declare sub glTexImage2D lib "opengl32.dll" alias "glTexImage2D" (byval dword, byval long, byval long, byval long, byval long, byval long, byval dword, byval dword, npixels as ANY)
declare sub glDeleteTextures lib "opengl32.dll" alias "glDeleteTextures" (byval long, textures as ANY)
declare function glGetError lib "opengl32.dll" alias "glGetError" () as dword
declare function wglMakeCurrent lib "OPENGL32.DLL" alias "wglMakeCurrent" (byval hdc as dword, byval hglrc as dword) as long
declare sub gluPerspective lib "glu32.dll" alias "gluPerspective" (byval fovy#, byval aspect#, byval zNear#, byval zFar as double)
declare sub glRotatef lib "OPENGL32.DLL" alias "glRotatef" (byval angle as single, byval x as single, byval y as single, byval z as single)
declare sub glDepthFunc lib "OPENGL32.DLL" alias "glDepthFunc" (byval func as dword)
declare sub glAlphaFunc lib "OPENGL32.DLL" alias "glAlphaFunc" (byval func as dword, byval ref as single)
global gsR(), gsG(), gsB() as single
global gColor() as long, gzRegistryPluginCXYZ as asciiz * 64
sub ColorInit()
dim gColor(1 TO 33) as long
gColor(1) = RGB(32,32,32)
gColor(2) = RGB(0,44,233)
gColor(3) = RGB(0,67,210)
gColor(4) = RGB(0,89,187)
gColor(5) = RGB(0,112,164)
gColor(6) = RGB(0,135,142)
gColor(7) = RGB(0,159,117)
gColor(8) = RGB(0,183,88)
gColor(9) = RGB(0,207,58)
gColor(10) = RGB(0,231,29)
gColor(11) = RGB(26,234,26)
gColor(12) = RGB(52,237,23)
gColor(13) = RGB(79,240,20)
gColor(14) = RGB(105,243,17)
gColor(15) = RGB(126,245,14)
gColor(16) = RGB(147,248,11)
gColor(17) = RGB(168,250,8)
gColor(18) = RGB(189,253,5)
gColor(19) = RGB(210,255,2)
gColor(20) = RGB(233,255,0)
gColor(21) = RGB(255,255,0)
gColor(22) = RGB(255,251,0)
gColor(23) = RGB(255,235,0)
gColor(24) = RGB(255,215,0)
gColor(25) = RGB(255,196,0)
gColor(26) = RGB(255,176,0)
gColor(27) = RGB(255,156,0)
gColor(28) = RGB(253,137,0)
gColor(29) = RGB(255,117,0)
gColor(30) = RGB(255,97,0)
gColor(31) = RGB(255,78,0)
gColor(32) = RGB(255,58,0)
gColor(33) = RGB(255,0,0)
end sub
function LevelColr(byval nLevel as long) as long
local nColor as long
nLevel = nLevel + 1: if nLevel > 33 then nLevel = 33
nColor = 0: if nLevel > 0 then nColor = gColor(nLevel)
function = nColor
end function
'// The main exported plugin's function would be bbProc, like this:
function BBProc alias "BBProc" (BYREF BBP as BBPLUGIN) export as long
local x, y, k, KK, nRet, Msg, wParam, lParam as long
local sDataString as STRING
static Mx, My, MDown as long
static UseFont as ZGLFONT
static Cx, _ '// Camera rotation
Cy, _ '// Camera rotation
Cz _ '// Zoom
as single
' static ptr_wglSwapIntervalEXT as dword
dim mt(1 TO 1) as static BBPTEXTURE
nRet = %BBP_SUCCESS
select case long BBP.Msg
case %BBP_RENDER
local Direction as long, Ax, Bx, Ay, By as single
local nLValue, nRValue as dword, UseColor as long
nLValue = (BBP.Lpeak / 700)
nRValue = (BBP.Rpeak / 700)
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
'// Draw coordinates using OpenGL font
UseColor = BBP_ColorARGB(255, RGB(20, 20, 148))
Af$ = "CX " + str$(cint(CX)) + " CY " + str$(cint(CY)) + " CZ " + str$(cint(CZ))
BBP_DrawGLText(BBP.ParentWindow, UseFont, 10, 10, (Af$), UseColor)
'BBP_DrawGLText(BBP.ParentWindow, UseFont, 10, 10 + UseFont.fontHeight, ("CY " + str$(cint(CY))), UseColor)
'BBP_DrawGLText(BBP.ParentWindow, UseFont, 10, 10 + UseFont.fontHeight * 2, ("CZ " + str$(cint(CZ))), UseColor)
glLoadIdentity()
glTranslatef(0.0, 0.0, Cz)'-50.0)
glrotatef(Cx, 1.0, 0.0, 0.0)
glrotatef(Cy, 0.0, 1.0, 0.0)
'// This is where the magic happens:
'// BBP.FFTsize returns a pointer to an area of memory containing an array of 256 singles.
'// This is then mapped to the fft() array where it can be accessed.
dim fft(BBP.FFTsize) as single at BBP.FFTdata
dim SoundBuffer(BBP.FFTsize) as single
'// Try and smooth out the buffer by averaging the last results:
for k = 0 TO 255
'// We use sqr to bring out the midtone of the music, otherwise the spectrum is very flat.
'// And fortunatly sqr is highy optimized in PowerBASIC
SoundBuffer(k) = sqr(sqr(fft(k))*2)
next
for Direction = -1 TO 1
if (Direction) then
for KK = 0 TO 2
k = KK * 16
glPushMatrix()
'// The iterator k goes from 0 (deepest bass) to 255 (highest treble pitch)
'// Ax is the distance from the center. Ay & By are width and height of the flares.
Ax = (KK * 16) / 64 * 125 * Direction
Ay = 2 + SoundBuffer(k) * (50 + k / 255 * 70) '// as k increases, the relative size of the signal
By = 2 + SoundBuffer(k) * (50 + k / 255 * 70) '// drops, so the (k / 255 * 20) compensates by boosting the signal at higher frequencies.
glColor4f(gsR(k) * SoundBuffer(k), gsG(k) * SoundBuffer(k), gsB(k) * SoundBuffer(k) + 0.1, 0.7)
glTranslatef(Ax, 0.0, 0.0)
glrotatef(Cx, 1, 0, 0)
glrotatef(Cy, 0, 1, 0)
glBegin(GL_QUADS)
glTexCoord2f(0,0): glVertex3f(-By , Ay, 0.0)
glTexCoord2f(1,0): glVertex3f( By , Ay, 0.0)
glTexCoord2f(1,1): glVertex3f( By ,-Ay, 0.0)
glTexCoord2f(0,1): glVertex3f(-By ,-Ay, 0.0)
glEnd()
glPopMatrix()
next
end if
next
'// Very important we must reassign BBP.RC to the new BBP.DC
'// Note: don't use permanent DC, this produce better and smoother display
wglMakeCurrent(BBP.DC, BBP.RC)
case %BBP_CREATE
'// Retrieve plugin details
BBP.Title = "Woofer"
BBP.Author = "Patrice Terrier"
BBP.Version = MAKDWD(1, 0) '// Version 1.0"
BBP.RenderTo = %BBP_OPENGL '// or %BBP_GDIPLUS, or %BBP_DIRECTX
gzRegistryPluginCXYZ = $RegistryPluginCXYZ + BBP.Title
case %BBP_INIT
'// May I ask you at which pretty pointer wglSwapIntervalEXT situated is ?
'ptr_wglSwapIntervalEXT = wglGetProcAddress("wglSwapIntervalEXT")
'// Do your code initialisation there
ColorInit()
'// Set random-number seed.
RANDOMIZE TIMER
BBP_SplitColorARGB(BBP.BackARGB, A?, R?, G?, B?)
Alpha! = A? + 1: Red! = R? + 1: Green! = G? + 1: Blue! = B? + 1
glClearColor(Red! / 256, Green! /256, Blue! / 256, Alpha! / 256)
glShadeModel(GL_SMOOTH) '// Enables Smooth Color Shading
glClearDepth(1.0) '// Depth Buffer Setup
glDisable(GL_DEPTH_TEST)'// Disable Depth Buffer
'**'glBlendFunc(GL_SRC_ALPHA, GL_ONE)
glBlendFunc(GL_ONE, GL_ONE)
glDepthFunc(GL_LESS) '// The type Of Depth Test To Do
glDisable(GL_LIGHTING)
glEnable(GL_BLEND)
glAlphaFunc(GL_GREATER, 0.01)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glEnable(GL_TEXTURE_2D)
mt(1).FullName = $BBP_PLUGIN_FOLDER + "Texture\Boomer.png": mt(1).ID = 1: mt(1).Square = 0
MakeMultipleTexture (byval varptr(mt(lbound(mt))), ubound(mt) - lbound(mt) + 1)
UseFont.fontName = "Arial"
UseFont.fontHeight = 10
UseFont.fontWeight = %FW_BOLD
BBP_BuildGLfont(BBP.DC, UseFont) ' Build OpenGL font for our OpenGL window
MakeColorLUT()
'// Retrieve CX, CY, CZ from registry
sDataString = BBP_GetReg(0, $RegistryKey, gzRegistryPluginCXYZ)
if (parsecount(sDataString) = 3) then
Cx = VAL(PARSE$(sDataString, 1))
CY = VAL(PARSE$(sDataString, 2))
Cz = VAL(PARSE$(sDataString, 3))
else
gosub ResetCXCYCZ
end if
case %BBP_SIZE
'// The size of the view port has changed.
local rAspect as double, rc as RECT
GetClientRect(BBP.ParentWindow, rc)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
rAspect = 0: if rc.nBottom then rAspect = rc.nRight / rc.nBottom
gluPerspective(50.0, rAspect, 0.01, 5000.0)
glMatrixMode(GL_MODELVIEW)
case %BBP_MOUSE
'// Handle all Windows mouse messages there
Msg = BBP.WinMsg: wParam = BBP.wParam: lParam = BBP.lParam
select case long Msg
case WM_MOUSEMOVE
x = LO(WORD, lParam): y = HI(WORD, lParam)
if MDown = MK_LBUTTON then
Cy = Cy + (x - Mx)
Cx = Cx + (y - My)
ELSEIF MDown = MK_RBUTTON then
Cy = Cy + (x - Mx)
Cz = Cz + (y - My)
end if
Mx = x: My = y
case WM_LBUTTONDOWN, WM_RBUTTONDOWN ', WM_MBUTTONDOWN, WM_XBUTTONDOWN
Mx = LO(WORD, lParam): My = HI(WORD, lParam)
if wParam = MK_LBUTTON or wParam = MK_RBUTTON then MDown = wParam
case WM_LBUTTONUP, WM_RBUTTONUP ', WM_MBUTTONUP, WM_XBUTTONUP
MDown = 0
'case WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK ', WM_MBUTTONDBLCLK, WM_XBUTTONDBLCLK
'case WM_MOUSEWHEEL
end select
case %BBP_KEYBOARD
'// Handle all Windows keyboard messages there
Msg = BBP.WinMsg: wParam = BBP.wParam: lParam = BBP.lParam
if (wParam = 32) then gosub ResetCXCYCZ
case %BBP_DESTROY
'// Save CX, CY, CZ to registry
if (CX or CY or CZ) then
sDataString = str$(cint(CX)) + "," + str$(cint(CY)) + "," + str$(cint(CZ))
BBP_SetReg(0, $RegistryKey, gzRegistryPluginCXYZ, (sDataString))
end if
'// Free up your resources there
DestroyTexture (byval varptr(mt(lbound(mt))), ubound(mt) - lbound(mt) + 1)
BBP_DeleteGLFont(UseFont) ' Free up the OpenGL font
case else
nRet = %BBP_ERROR
end select
function = nRet
exit function
ResetCXCYCZ:
Cx = -600: Cy = -900: Cz = -150
return
end function
sub MakeColorLUT()
local k, RGBColor as long
dim gsR(255), gsG(255), gsB(255) as single
for k = 0 TO 255
RGBColor = LevelColr(k)
gsR(k) = (BBP_GetRValue(RGBColor) + 1) / 256
gsG(k) = (BBP_GetGValue(RGBColor) + 1) / 256
gsB(k) = (BBP_GetBValue(RGBColor) + 1) / 256
next
end sub
sub MakeMultipleTexture (byval tp as BBPTEXTURE ptr, byval N as long)
local mtCount, k, nRet, xSize, ySize, OkDelete as long
dim mt(1 TO N) as BBPTEXTURE at tp
mtCount = ubound(mt()) - lbound(mt()) + 1
if (mtCount) then
dim Texture(1 TO mtCount) as long
for k = 1 TO mtCount
Texture(k) = mt(k).Texture: if Texture(k) then OkDelete = -1
next
if OkDelete then glDeleteTextures(mtCount, Texture(1))
glGenTextures(mtCount, Texture(1)): nRet = glGetError()
if (nRet = 0) then
for k = 1 TO mtCount
redim PixelArray(0) as byte
if (BBP_CreateGLTextureFromFile(mt(k).FullName, xSize, ySize, PixelArray(), mt(k).Square)) then
mt(k).Texture = Texture(k)
glBindTexture(GL_TEXTURE_2D, Texture(k)): nRet = glGetError
if (nRet = 0) then
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, 4, xSize&, ySize&, 0, GL_RGBA, GL_UNSIGNED_BYTE, PixelArray(0))
end if
end if
next
end if
end if
end sub
sub DestroyTexture(byval tp as BBPTEXTURE ptr, byval N as long)
local k, mtCount, OkDelete as long
dim mt(1 TO N) as BBPTEXTURE at tp
mtCount = ubound(mt()) - lbound(mt()) + 1
if (mtCount) then
dim Texture(1 TO mtCount) as long
for k = 1 TO mtCount
Texture(k) = mt(k).Texture: if Texture(k) then OkDelete = -1
next
if (OkDelete) then glDeleteTextures(mtCount, Texture(1))
end if
end sub