Get the Flash Player to see the wordTube Media Player.


This is a small sample of an OpenGL kaleidoscope I’m working on using the plasma code also posted on this site.

I’m currently struggling with texture mipmapping artifacts in OSX. Win32 versions seem to work (as shown) – although end results could be very driver dependent. I’ll post the code when I’m done.

Comments No Comments »

Get the Flash Player to see the wordTube Media Player.

For a while now I’ve wanted to port my favourite plasma algorithm (which is the heart of my screensaver Angelicus) to Blitzmax. I’m happy to say I have finally done just that. Below is the code from a module you can download here: gibbongames.mod.

To get the code to run, unzip the download into the Blitzmax\mod folder. For reference, this is what the full path looks like on my XP installataion:

C:\Program Files\BlitzMax\mod\gibbongames.mod\plasma.mod

Open up Blitzmax and hit Ctrl-D to compile the module. Then open gibbongames.mod\plasma.mod\Examples\plasma.bmx and compile it to run the demo.

There’s lots of fun to be had playing with the various settings in the plasma.Create() call. So by all means experiment.

Windows users without Blitzmax can run this tiny demo program to see what I am talking about: plasma.zip.

This is the demo code:

' ----------------------------------------------------------------
Rem
	bbdoc:   	Plasma demo by David De Candia Feb 2009
	credit:  	Plasma is a mutli-colour port of an C algorithm by Michael Bevin, Jan Miller and Erik Hansen. 
			See FX library at http://www.geocities.com/SiliconValley/Vista/9582/ for original source
End Rem
 
SuperStrict 
 
Framework BRL.GLMax2D 					'Framework BRL.d3d7Max2D
Import BRL.Random
Import GibbonGames.Plasma	
 
SetGraphicsDriver GLMax2DDriver()		'D3D7Max2DDriver()
Local window_width:Int = 320	
Local window_height:Int= 240
Graphics window_width, window_height, 0
 
Local plasma:TPlasma 	= New TPlasma.Create(	128,..	' pixmap width & height (must be power of 2)
										4,..		' contrast:Int
										0.065,..  ' speed:Float
										75,..	' complexity:Int
										10,..	' interference:Float (try higher numbers for a less "busy" appearance)
										1,..		' brighten:Int (0 for darken)
										1,..		' pixel_step:Int (speed up plasma alogirithm, sacrificing definition as you go higher - try 1,2,4,8,16)
										3)		' num_plasmas (1 to 3, 3 default)
Local image:TImage
 
While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
 
	plasma.Draw()
	Image=LoadImage(plasma.Pixmap)
	DrawImageRect Image,0,0,window_width, window_height
	Flip 1 
 
Wend
End

And this is the module source, containing the plasma algorithm. Thanks to Michael Bevin for the C source.

Oh, and a little tip: if you click on the source box below you can scroll the code with the left/right arrow keys.

?Download plasma.bmx
SuperStrict
' Copyright (c) 2009 David De Candia
' All rights reserved.
'
' Redistribution and use in source and binary forms, with or without
' modification, are permitted provided that the following conditions are met:
'     * Redistributions of source code must retain the above copyright
'       notice, this list of conditions and the following disclaimer.
'     * Redistributions in binary form must reproduce the above copyright
'       notice, this list of conditions and the following disclaimer in the
'       documentation and/or other materials provided with the distribution.
'     * Neither the auther nor the names of its contributors may be used to 
'       endorse or promote products derived from this software without specific
'       prior written permission.
'
' THIS SOFTWARE IS PROVIDED BY David De Candia ``AS IS'' AND ANY
' EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
' WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
' DISCLAIMED. IN NO EVENT SHALL David De Candia BE LIABLE FOR ANY
' DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
' (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
' LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
' ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
' (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
' SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'
 
Rem
bbdoc: Plasma
about: Pixmap-based real-time plasma algorithm
End Rem
Module gibbongames.plasma
 
ModuleInfo "Version: 1.0 29th October 2008"
ModuleInfo "Author: David De Candia"
ModuleInfo "Contact: david@gibbongames.com"
ModuleInfo "URL: www.gibbongames.com"
ModuleInfo "About: Real-time plasma algorithm for PF_RGBA8888 based pixmaps"
ModuleInfo "Credit: Plasma source: Michael Bevin, Jan Miller and Erik Hansen. See FX library at http://www.geocities.com/SiliconValley/Vista/9582/ for original C source"
 
Import BRL.GLMax2D 
Import BRL.Random
 
' ----------------------------------------------------------------
Rem
	bbdoc:   
	about:    
End Rem	
Type TPlasmaStructure
 
	Field Table1:Byte[]
	Field Table2:Byte[]
 
	Field Width:Int
	Field Height:Int
	Field PlasmaType:Int
 
	Const MAX_CIRCLES:Int = 8
 
	Field Circle:Float[MAX_CIRCLES]
	Field Roll:Int
 
End Type
 
' ----------------------------------------------------------------
Rem
	bbdoc:   
	about:  
	credit: 
End Rem
Type TPlasma
 
	Const BLUE_PLASMA:Int 	= 0,..
		 GREEN_PLASMA:Int 	= 1,..
		 RED_PLASMA:Int 	= 2,..
		 MAX_PLASMAS:Int	= 3
 
	Field NumPlasmas:Int 	= 3
 
	Field f_PlasmaSpeed:Float
	Field f_PlasmaRipples:Float = 6
	Field PlasmaComplexity:Int 
	Field f_PlasmaInterference:Float 
	Field PlasmaContrast:Int 
	Field PixelStep:Int		' 1 to 8, even numbers after 1. The higher the pixel step the faster the algorithm, and the lower the plasma resolution
	Field PlasmaBrighten:Int	' 0 or 1
 
	Const F_RADS:Float = 57.2957795
 
	'	All plasmas have the same width and height - must be power of 2
	Field Width:Int
	Field Height:Int
 
	Field Plasma:TPlasmaStructure[MAX_PLASMAS]
 
	'	Plasma is drawn to here
	Field Pixmap:TPixmap
 
	' ----------------------------------------------------------------
	Rem
		bbdoc:   
		about:    
	End Rem	
	Method Create:TPlasma(_width:Int, _contrast:Int = 4, _f_speed:Float = 0.07, _complexity:Int = 100, _f_interference:Float = 9.5, _brighten:Int = 1, _pixel_step:Int = 1, _num_plasmas:Int = 3 )
 
		SeedRnd MilliSecs()
 
		PlasmaContrast 		= _contrast
		PlasmaComplexity		= _complexity
		f_PlasmaInterference 	= _f_interference
		PlasmaBrighten		 	= _brighten
		f_PlasmaSpeed			= _f_speed
		PixelStep				= _pixel_step
		NumPlasmas			= Max(1, Min(MAX_PLASMAS,_num_plasmas))
 
		' Create 3 plasmas, one for each colour channel and overlay them during render					
		If NumPlasmas > RED_PLASMA Then Init(Plasma[RED_PLASMA], _width, _width)
		If NumPlasmas > GREEN_PLASMA Then Init(Plasma[GREEN_PLASMA], _width,_width)
		If NumPlasmas > BLUE_PLASMA Then Init(Plasma[BLUE_PLASMA], _width, _width)
 
		' Plasma is rendered on this
		Pixmap = CreatePixmap(_width, _width,PF_RGBA8888)
 
		Return Self
 
	End Method
 
	' ----------------------------------------------------------------
	Rem
		bbdoc:   _f_frame_time currently unused in favour of vsync
		about:    
	End Rem	
	Method Draw(_f_frame_time:Float = 1.0/60.0)
 
		Local double_width:Int = Width *2
 
		Local xx1:Int[MAX_PLASMAS],xx2:Int[MAX_PLASMAS],xx3:Int[MAX_PLASMAS],xx4:Int[MAX_PLASMAS]
		Local x1:Int[MAX_PLASMAS],y1:Int[MAX_PLASMAS],x2:Int[MAX_PLASMAS],y2:Int[MAX_PLASMAS],x3:Int[MAX_PLASMAS],y3:Int[MAX_PLASMAS],x4:Int[MAX_PLASMAS],y4:Int[MAX_PLASMAS]
 
		Local ubyte:Byte[MAX_PLASMAS]
 
		'	If you were frame limiting the code via f_frame_time, you'd prob do it here
		Local f_sway:Float = F_RADS * f_PlasmaSpeed 
 
		Local wo4:Int = Width/4
   		Local wo2:Int = Width/2
   		Local ho2:Int = Height/2
 
		Local f_sways:Float[] = [ 0.0425 * f_sway , -0.05* f_sway, 0.15* f_sway, -0.10* f_sway, 0.20* f_sway, -0.075* f_sway, 0.175* f_sway, -0.025* f_sway ]
 
		For Local plasma_id:Int = 0 Until NumPlasmas
 
			For Local circle_id:Int = 0 Until TPlasmaStructure.MAX_CIRCLES 
				Plasma[plasma_id].Circle[circle_id] :+  f_sways[circle_id]	
			Next
 
			x2[plasma_id] = wo2 + Int( (Float(wo2) * Sin(Plasma[plasma_id].Circle[0])) )
			y2[plasma_id] = ho2 + Int( (Float(ho2) * Cos(Plasma[plasma_id].Circle[1])) )
			x1[plasma_id] = wo2 + Int( (Float(wo2) * Cos(Plasma[plasma_id].Circle[2])))
			y1[plasma_id] = ho2 + Int( (Float(ho2) * Sin(Plasma[plasma_id].Circle[3])))
			x3[plasma_id] = wo2 + Int( (Float(wo2) * Cos(Plasma[plasma_id].Circle[4])))
			y3[plasma_id] = ho2 + Int( (Float(ho2) * Sin(Plasma[plasma_id].Circle[5])))
			x4[plasma_id] = wo2 + Int( (Float(wo2) * Cos(Plasma[plasma_id].Circle[6])))
			y4[plasma_id] = ho2 + Int( (Float(ho2) * Sin(Plasma[plasma_id].Circle[7])))
 
			xx1[plasma_id] = double_width * y1[plasma_id] + x1[plasma_id]
			xx2[plasma_id] = double_width * y2[plasma_id] + x2[plasma_id]
			xx3[plasma_id] = double_width * y3[plasma_id] + x3[plasma_id]
			xx4[plasma_id] = double_width * y4[plasma_id] + x4[plasma_id]
 
		Next
 
		Local colour_value_a:Int, colour_value_b:Int, colour_value_c:Int
		Local colour_to_plot:Int
		Local y_offset:Int
		Local alpha:Int = $ff000000'255 Shl 24
		Local table_index:Int 
		Local plasma_id:Int
		Local pixel_id:Int
		Local x:Int
		Local pixel:Byte Ptr
 
		'	For each y pixel in the pixmap
		For Local y:Int = 0 Until Height
 
			y_offset = double_width * y;
 
			table_index = 0
 
			x = 0
 
			'	Write 1 line of pixels
 			While x < Width 
 
				For plasma_id:Int = 0 Until NumPlasmas
 
					ubyte[plasma_id] = 	Plasma[plasma_id].Table1[table_index + y_offset + xx1[plasma_id]] +..	
									Plasma[plasma_id].Table2[table_index + y_offset + xx3[plasma_id]] +..	
									Plasma[plasma_id].Table2[table_index + y_offset + xx4[plasma_id]] +..	
									Plasma[plasma_id].Table2[table_index + y_offset + xx2[plasma_id]]	
 
 
					'	Beautify - essential!
					If ubyte[plasma_id] & 128 Then ubyte[plasma_id] =  ~ubyte[plasma_id]
					'
				Next
 
				colour_value_a	=  ubyte[BLUE_PLASMA] 		'	BLUE
				colour_value_b	=  ubyte[GREEN_PLASMA]  Shl 8	'	GREEN
				colour_value_c	=  ubyte[RED_PLASMA] Shl 16	'	RED
 
				'	Shl 1 brightens everything
				colour_to_plot = alpha | ((colour_value_a|colour_value_b|colour_value_c) Shl PlasmaBrighten)
 
				'	Grab the memory address of the next pixel to write to 
				'	This will only work for 4 byte pixmaps like RGBA - else use the slower PixelPtr call
				pixel = Pixmap.pixels + y * Pixmap.pitch + x * 4
				'pixel=Pixmap.PixelPtr(x,y)
 
				' Writing a bunch of the same colour pixels at once saves FPS but decreases resolution
				For pixel_id = 0 Until PixelStep
 
					' This is more generic and safer - in that it detects the dest surface type before writing, but it is also slower	
					'WritePixel Pixmap,x+pixel_id,y,colour_to_plot
					pixel[0]=colour_to_plot Shr 16 ; pixel[1]=colour_to_plot Shr 8 ; pixel[2]=colour_to_plot ; pixel[3]=colour_to_plot Shr 24
					pixel :+ 4
 
				Next
 
				table_index :+  1
 
				x :+ PixelStep
 
			Wend'x
 
		Next 'y
 
	End Method
 
	' ----------------------------------------------------------------
	Rem
		bbdoc:   
		about:    
	End Rem
	Method Init(_plasma:TPlasmaStructure, _width:Int, _height:Int)
 
		'	Safety
		If Not _plasma Then Return
 
		Local height_index:Int 
		Local width_index:Int 
		Local k:Int
		Local double_width:Int
		Local double_height:Int
 
		Local contrast:Int = PlasmaContrast
		Local constant_a:Int
		Local f_angle_a:Float
		Local f_angle_b:Float
 
		Local f_temp:Float
 
		If _plasma
 
			_plasma.Width 	= _width
			_plasma.Height = _height
			Width		= _width
			Height		= _height
 
			double_height 	= _height*2
			double_width 	= _width * 2 
 
			f_angle_a		= f_PlasmaRipples
			f_angle_b		= f_PlasmaInterference
			constant_a 	= PlasmaComplexity
 
			For Local circle_id:Int = 0 Until TPlasmaStructure.MAX_CIRCLES
				_plasma.Circle[circle_id] = F_RADS  * Float(Rand(0, 65535)) / 16384.0
				If circle_id & 1 Then _plasma.Circle[circle_id] :* -1
			Next
 
			_plasma.PlasmaType = contrast
 
			'	Each table is double width, double height 
			_plasma.Table1 = New Byte[_width*_height*4]
			_plasma.Table2 = New Byte[_width*_height*4]
 
			Local table_index:Int
 
			While height_index < _height
 
				width_index = 0
				k = (_height-height_index) * (_height-height_index)
 
				While width_index < _width
 
					f_temp = Sqr(16+k+(_width-width_index)*(_width-width_index)-4)
 
					_plasma.Table1[table_index] = Byte( f_temp * f_angle_a / contrast)
					_plasma.Table2[table_index] = Byte( (Sin(F_RADS*f_temp/f_angle_b) + 1) * constant_a / contrast)
 
					width_index :+ 1
					table_index :+ 1
 
				Wend 'width_index < _width
 
				Local symmetry_index:Int = 0
				Local middle:Int = table_index - 1
 
				'	Mirror Symmetry on X - copy the current line backwards
				While width_index < double_width
 
					_plasma.Table1[table_index] = _plasma.Table1[middle - symmetry_index]
					_plasma.Table2[table_index] = _plasma.Table2[middle - symmetry_index]
 
					table_index 	:+1
					symmetry_index :+ 1
 
					width_index :+ 1
 
				Wend
 
				height_index :+ 1
 
			Wend 'height_index < height
 
			' Mirror symmetry on Y			
			While height_index < double_height
 
				MemCopy (Varptr(_plasma.Table1[height_index*double_width]), Varptr(_plasma.Table1[(double_height-height_index-1) * double_width]), double_width)
				MemCopy (Varptr(_plasma.Table2[height_index*double_width]), Varptr(_plasma.Table2[(double_height-height_index-1) * double_width]), double_width)
 
				height_index :+ 1
			Wend
 
		EndIf ' if _plasma
 
	End Method
 
	' ----------------------------------------------------------------
	Rem
		bbdoc:   
		about:    
	End Rem	
	Method New()
		For Local plasma_id:Int = 0 Until MAX_PLASMAS
			Plasma[plasma_id] = New TPlasmaStructure
		Next
	End Method
 
End Type

Comments No Comments »

Here’s another of my permanent reminder web sticky notes, covering how to set up a PostgreSQL database for Blitzmax in Windows.

• Your windows file system needs to be NTFS
Download the latest PostgreSQL installer package
Jump to this installer walk-through page
• Step through the walk-through. Choose the defaults in most cases. Make sure you write down all your settings!

My settings were:

Account name: postgres
domain: DAVIDDECAND6915
pass: account_sql_pass
port: 5432
UTF8 encoding for server and client
Localhost connections only (no remote connections)
superuser name: superuser_name
pass: superuser_pass

• Navigate to Control Panel/System/Advanced/Environment Variables and add the PostgreSQL bin location to the end of your PATH. Mine looked like this: ;C:\Program Files\PostgreSQL\8.3\bin
Download Brucey’s BAH.Database and BAH.dbpostgreSQL.mod
• Place them in the folder as such: Blitzmax/mod/bah.mod/database.mod and Blitzmax/mod/bah.mod/dbpostgresql.mod
• Navigate to BlitzMax\mod\bah.mod\dbpostgresql.mod\lib and copy libpg.a and paste it in BlitzMax\lib
• Restart Windows to let the environment variables PATH settings take effect
• Load up and run the test files in BlitzMax\mod\bah.mod\dbpostgresql.mod\tests
• Edit the LoadDatabase call with your own databae specifics. My LoadDatabase call looked like this:

Local db:TDBConnection = LoadDatabase("POSTGRESQL", "postgres", "localhost", 5432, "superuser_name", "superuser_pass")

• Ctrl-D in Blitzmax to compile the new modules and then Compile and run the test.bmx file.
• If all is well, it should spit out something like:

DebugLog:1. Name = Alfred Aho
DebugLog: 2. Name = Brian Kernighan
DebugLog:3. Name = Peter Weinberger
NOTICE: CREATE TABLE/PRIMARY KEY well create implicit index "person_pkey" for table "person"

Comments No Comments »