Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - backspace

#1
Hi there.
I know with DirectX, with c++ i can get the device context handle, and do some stuff directly in the DX screen, I am however pretty new to OpenGL, and want to know if I can get the background buffer address, widow address, or whatever is appropriate, and do something similar. Why I wish to know this, is because there are some image manipulation routines that I used in DX, and wish to do the same - if it is possible with OGL. Is this at all possible with GLBasic?
Any help in this regard will be very much appreciated.
#2
I'm really getting the hang of GLBasic now. It's time to give back for all the help I've received on the forum.

ISAM.gbal is included in the attached zip file, together with all sources.

ISAM is a GLBasic library that uses a UNIX concept of an indexed database.
ISAM stands for Indexed Sequential Access Method. A way of storing indexed data in a text file.

The library provides a TYPE named _ISAM, which can be used to manage simple databases on all platforms
The database is used in memory, and it can be saved to a textfile, and later loaded on demand

You can use as many databases at the same time as you wish.
You declare a database by using the _ISAM TYPE

friends AS _ISAM -is all that is needed to initialize the database
You can have as many rows and columns in the database as you wish.
You don't waste memory because row/column fields are only created when you "set" them.
All data is saved as strings, so you will need to convert the data if you wish to use them as numbers.

The ISAM library source
Code (glbasic) Select
// ------------------------------------------------------- //
// Project: ISAM
// Indexed Sequential Access Method Database file Manager
// ------------------------------------------------------ //


TYPE _ISAMINFO
index$
field$[]
info$[]
ENDTYPE

TYPE _ISAM
info[] AS _ISAMINFO

//! set: This function sets a variable to the database.
//! The index is used as a key to a table row
//! Each table row may have multiple fields, but must use the same index to add the field to the row
//! Each entry is only stored as a string. You will need to convert it in your code, if you wish to use numbers
//! If a field already exists, the data in that field will be updated.
//!
//! Parameters:
//! index$: The index for the row in the database
//! field$: The name of the column field in the index row of the database
//! info$ : The info you wish to store in the database field$ in the index$ row
//!
//! Returns: Nothing
//!
//! Example: set("JoeH", "Name", "Joseph"); set("JoeH","Surname","Higgins")
FUNCTION set: index$, field$, info$
LOCAL i,L,j,found
L=LEN(self.info[])
found = FALSE
FOR i = 0 TO LEN(self.info[])-1
IF index$ = self.info[i].index$
//first look for item to replace
FOR j = 0 TO LEN(self.info[i].field$[])-1
IF self.info[i].field$[j] = field$
self.info[i].info$[j] = info$
RETURN //change made - skip rest of function
ENDIF
NEXT
DIMPUSH self.info[i].field$[], field$
DIMPUSH self.info[i].info$[],info$
found=TRUE
BREAK
ENDIF
NEXT
IF NOT found
L=BOUNDS(self.info[], 0)
REDIM self.info[L+1]
self.info[L].index$ = index$
DIMPUSH self.info[L].field$[], field$
DIMPUSH self.info[L].info$[],info$
ENDIF
ENDFUNCTION

//! get: This function gets a variable from the database.
//! The index is used as a key to a table row
//! The index and the field must exist in the database, else the function returns a blank string
//!
//! Parameters:
//! index$: The index for the row in the database
//! field$: The name of the column field in the index row of the database
//!
//! Returns: On success, rerurns the info from the field. On failure, returns a blank string
//!
//! Example: name$ = get("JoeH", "Name")
FUNCTION get$: index$, field$
LOCAL i,j,L
LOCAL info$
FOR i = 0 TO LEN(self.info[])-1
IF index$ = self.info[i].index$
FOR j = 0 TO LEN(self.info[i].field$[])-1
IF self.info[i].field$[j] = field$
info$ = self.info[i].info$[j]
RETURN info$
ENDIF
NEXT
ENDIF
NEXT
RETURN ""
ENDFUNCTION

//! indexcount: This function returns the number of rows in the database.
//!
//! Parameters:
//! None
//!
//! Returns: The number of rows in the database
//!
//! Example: rows% = indexcount()
FUNCTION indexcount:
RETURN LEN(self.info[])
ENDFUNCTION

//! getindex$: This function gets the index string for the specified database row
//!
//! Parameters:
//! num%:  The number of the database row to access
//!
//! Returns: The index string for the specified database row
//!
//! Example: index$ = getindex$(2)
FUNCTION getindex$: num%
IF LEN(self.info[]) < 1 THEN RETURN
RETURN self.info[num].index$
ENDFUNCTION

//! fieldcount: This function gets the number of fields in an indexed database row
//!
//! Parameters:
//! index$: The index name of the database row to query
//!
//! Returns: The number of fields in the indexed row, or 0 if there are no fields
//!
//! Example: numFields = fieldcount("JoeH")
FUNCTION fieldcount: index$
LOCAL i
FOR i = 0 TO LEN(self.info[])-1
IF self.info[i].index$ = index$
RETURN LEN(self.info[i].field$[])
ENDIF
NEXT
RETURN 0
ENDFUNCTION

//! getfield$: This function gets the name of the specified field column number in the indexed row
//!
//! Parameters:
//! index$: The index name for the database row
//! num%:   The number of the field column in the row
//!
//! Returns: The name of the field column, or "" if the field does not exist
//!
//! Example: filed/name$ = getfield$("JoeH", 1)
FUNCTION getfield$: index$, num%
LOCAL i,j,L
FOR i = 0 TO LEN(self.info[])-1
IF self.info[i].index$ = index$
RETURN self.info[i].field$[num]
ENDIF
NEXT
RETURN ""
ENDFUNCTION

//! delindex: This function deletes an entire indexed row from the database
//! Note: This action is not reversable.
//!
//! Parameters:
//! index$: The index name of the database row ro delete
//!
//! Returns: 1 on success, -1 on failure
//!
//! Example: delindex("JoeH")
FUNCTION delindex: index$
LOCAL i,L
FOR i = 0 TO LEN(self.info[])-1
IF self.info[i].index$ = index$
DIMDEL self.info[],i
RETURN 1
ENDIF
NEXT
RETURN -1
ENDFUNCTION

//! save: This function saves the entire database as a textfile to disk
//!
//! Parameters:
//! filename$: The file name to which to save the database
//!
//! Returns: 1 on success, -1 on failure
//!
//! Example: save("myfriends.db")
FUNCTION save: filename$
LOCAL ok = OPENFILE(1, filename$,0)
LOCAL i,j,s$
IF NOT ok THEN RETURN -1
s$ = LEN(self.info[])
WRITESTR 1, s$+"\n"
FOR i = 0 TO LEN(self.info[])-1
WRITESTR 1, self.info[i].index$ + "\n"
s$ = LEN(self.info[i].field$[])
WRITESTR 1,s$ + "\n"
FOR j = 0 TO LEN(self.info[i].field$[])-1
WRITESTR 1, self.info[i].field$[j]+"\n"
WRITESTR 1, self.info[i].info$[j]+"\n"
NEXT
NEXT
CLOSEFILE 1
RETURN 1
ENDFUNCTION


//! load: This function loads a previously saved database back into memory
//!
//! Parameters:
//! filename$: The file name from which to read the database
//!
//! Returns: 1 on success, -1 on failure
//!
//! Example: load("myfriends.db")
FUNCTION load: filename$
REDIM self.info[0]
IF NOT DOESFILEEXIST(filename$) THEN RETURN -1
LOCAL ok = OPENFILE(1, filename$,1)
IF NOT ok THEN RETURN -1
LOCAL xi,xj,xIdxcount%,xfieldcnt%, s$
LOCAL xindex$,xfield$,xinfo$
IF NOT ok THEN RETURN
READLINE 1,s$
xIdxcount =  s$
FOR xi = 0 TO xIdxcount-1
READLINE 1, xindex$
READLINE 1, s$
xfieldcnt = s$
FOR xj = 0 TO xfieldcnt -1
READLINE 1,xfield$
READLINE 1,xinfo$
self.set(xindex$,xfield$,xinfo$)
NEXT
NEXT
CLOSEFILE 1
RETURN 1
ENDFUNCTION
ENDTYPE

//! ISAM is a GLBasic library that uses a UNIX concept of an indexed database.
//! ISAM stands for Indexed Sequential Access Method. A way of storing indexed data in a text file.
//!
//! The library provides a TYPE named _ISAM, which can be used to manage simple databases on all platforms
//! The database is used in memory, and it can be saved to a textfile, and later loaded on demand
//!
//! You can use as many databases at the same time as you wish.
//! You declare a database by using the _ISAM TYPE
//!
//! friends AS _ISAM    -is all that is needed to initialize the database
//! You can have as many rows and columns in the database as you wish.
//! You don't waste memory because row/column fields are only created when you "set" them.
//! All data is saved as strings, so you will need to convert the data if you wish to use them as numbers.
//!
//!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//! An example of using the database
//!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//!
//! LOCAL friends AS _ISAM
//! LOCAL info$
//! LOCAL i
//! LOCAL field$
//! LOCAL index$
//!
//! friends.set("JoeH","Name","Joe")
//! friends.set("JoeH","Surname","Higgins")
//! friends.set("JoeH","Phone","123-4567")
//! friends.set("JoeH","Birthday","12-12-90")
//! friends.set("JoeH","Email","joeh@somewhere.earth")
//!
//! friends.set("AnneP","Name","Anne")
//! friends.set("AnneP","Surname","Pigtails")
//! friends.set("AnneP","Phone","765-4321")
//! friends.set("AnneP","Birthday","11-11-91")
//! friends.set("AnneP","Email","annepig@somewhere.moon")
//!
//! friends.set("AlbertE","Name","Albert")
//! friends.set("AlbertE","Surname","Einstein")
//! friends.set("AlbertE","Phone","755-1212")
//! friends.set("AlbertE","Birthday","01-01-1901")
//! friends.set("AlbertE","Email","albert.einstein@relativity.e=mc2")
//!
//! friends.set("SrIsac","Name","Isac")
//! friends.set("SrIsac","Surname","Newton")
//! friends.set("SrIsac","Phone","001-00706")
//! friends.set("SrIsac","Birthday","11-11-61")
//! friends.set("SrIsac","Email","isac.apple@under.tree")
//! friends.set("SrIsac","Birthday","03-03-63") //change
//!
//! DEBUG friends.indexcount()
//!
//! FOR i = 0 TO friends.indexcount()-1
//! DEBUG friends.getindex$(i)+"\n"
//! NEXT
//!
//! friends.delindex("AlbertE")
//!
//! index$ = friends.getindex$(2)
//!
//! DEBUG "\n"
//!
//! FOR i = 0 TO friends.fieldcount(index$)-1
//! DEBUG friends.getfield$(index$, i)+"\n"
//! NEXT
//!
//! DEBUG "\n"
//!
//! FOR i = 0 TO friends.fieldcount(index$)-1
//! field$ = friends.getfield$(index$, i)
//! DEBUG friends.get$(index$,field$)+"\n"
//! NEXT
//!
//! friends.save("testfile")
//!
//! friends.load("testfile")
FUNCTION __help__:
ENDFUNCTION


The ISAM test program
Code (glbasic) Select
// --------------------------------- //
// Project: ISAM - Testfile
// --------------------------------- //

LOCAL friends AS _ISAM
LOCAL info$
LOCAL i
LOCAL field$
LOCAL index$

friends.set("JoeH","Name","Joe")
friends.set("JoeH","Surname","Higgins")
friends.set("JoeH","Phone","123-4567")
friends.set("JoeH","Birthday","12-12-90")
friends.set("JoeH","Email","joeh@somewhere.earth")

friends.set("AnneP","Name","Anne")
friends.set("AnneP","Surname","Pigtails")
friends.set("AnneP","Phone","765-4321")
friends.set("AnneP","Birthday","11-11-91")
friends.set("AnneP","Email","annepig@somewhere.moon")

friends.set("AlbertE","Name","Albert")
friends.set("AlbertE","Surname","Einstein")
friends.set("AlbertE","Phone","755-1212")
friends.set("AlbertE","Birthday","01-01-1901")
friends.set("AlbertE","Email","albert.einstein@relativity.e=mc2")

friends.set("SrIsac","Name","Isac")
friends.set("SrIsac","Surname","Newton")
friends.set("SrIsac","Phone","001-00706")
friends.set("SrIsac","Birthday","11-11-61")
friends.set("SrIsac","Email","isac.apple@under.tree")
friends.set("SrIsac","Birthday","03-03-63") //change

DEBUG friends.indexcount()

FOR i = 0 TO friends.indexcount()-1
DEBUG friends.getindex$(i)+"\n"
NEXT

friends.delindex("AlbertE")

index$ = friends.getindex$(2)

DEBUG "\n"

FOR i = 0 TO friends.fieldcount(index$)-1
DEBUG friends.getfield$(index$, i)+"\n"
NEXT

DEBUG "\n"

FOR i = 0 TO friends.fieldcount(index$)-1
field$ = friends.getfield$(index$, i)
DEBUG friends.get$(index$,field$)+"\n"
NEXT

friends.save("testfile")

friends.load("testfile")



[attachment deleted by admin]
#3
I took on the challenge to make a 3D splined path editor, to test out my new GLBasic skills, and I got a reasonable demo working.
However I have run into a brick wall with the QuadraticBezier3d, Not the function itself, that works brilliantly, but I'm rather stuck on how to make a continuous spline that runs through all 4 points that I use. The idea is to increase the key points on request, and generate splines as required. But alas my skills have dried up at this point.
I use the Bezier curves library from Hemlos to do the splines, but I am missing something along the way.
Any guidance will be most welcome

I've made certain arrays Global in the library in order to access them in my program.

Here's the program so far.
Code (glbasic) Select

//SETCURRENTDIR("Media")

//LOADFONT "..smalfont.png", 1
//SETFONT 1

TYPE POINT
x#
y#
z#
ENDTYPE

GLOBAL points[] AS POINT
GLOBAL splines[] AS POINT
GLOBAL waypoints[] AS POINT
GLOBAL numPoints = 4  //Key points for generating bezier curve points
GLOBAL extent# = 300  //Set pixel graph size: 100 means from -100 to +100. Change to desired path scale
GLOBAL CALC = FALSE
GLOBAL maxPoints = 30 //Bexier points: MUST be divisable by 2, else the calculations will fall over
LOCAL keyPoint = 0    //current key point
LOCAL i
LOCAL steps#
LOCAL angle = 270
LOCAL UpAngle = 0
LOCAL distanceP# = 2.5
LOCAL help = 1


SetupPoints()

WHILE TRUE
IF KEY(203) THEN angle = angle - 1 //left arrow
IF KEY(205) THEN angle = angle + 1 //right arrow
IF KEY(200) THEN UpAngle = UpAngle +1 //up arrow
IF KEY(208) THEN UpAngle = UpAngle -1 //down arrow
IF KEY(59) THEN help = -help; WHILE KEY(59); WEND //F1
IF KEY(15) THEN keyPoint = keyPoint+1;WHILE KEY(15); WEND //Tab
IF keyPoint > numPoints-1 THEN keyPoint = 0

IF KEY(17) //W
INC points[keyPoint].z 
CALC = FALSE
ENDIF

IF KEY(31) //S
DEC points[keyPoint].z 
CALC = FALSE
ENDIF

IF KEY(30) //A
INC points[keyPoint].x   //Reverse this if you prefer
CALC = FALSE
ENDIF

IF KEY(32) //D
DEC points[keyPoint].x  //Reverse this if you prefer
CALC = FALSE
ENDIF

IF KEY(19) //R
INC points[keyPoint].y 
CALC = FALSE
ENDIF

IF KEY(33) //F
DEC points[keyPoint].y 
CALC = FALSE
ENDIF



X_MAKE3D 1, 10000, 45
X_CAMERA COS(angle)*extent*distanceP, SIN(UpAngle)*extent*distanceP, SIN(angle)*extent*distanceP,  0, 0, 0

//grid
steps = extent*2/20
FOR i = -extent TO extent STEP steps
// XY grid
X_LINE -extent,i,0, extent,i,0, 0.1, RGB(0,0,60)
X_LINE i,-extent,0, i,extent,0, 0.1, RGB(0,0,60)
// XZ grid
X_LINE -extent,0,i, extent,0,i, 0.1, RGB(60,0,0)
X_LINE i,0,-extent, i,0,extent, 0.1, RGB(60,0,0)
//YX grid
X_LINE 0,-extent,i, 0,extent,i, 0.1, RGB(0,60,0)
X_LINE 0,i,-extent, 0,i,extent, 0.1, RGB(0,60,0)
NEXT

//z=0 indicator
X_LINE 0,0,0, 0,0,extent, 3, RGB(255,0,0)

//draw points
FOR i = 0 TO numPoints-1
IF i <> keyPoint
X_DOT points[i].x, points[i].y, points[i].z,10, RGB(0,255,0) //10=size of keypoint: change as required
ENDIF
NEXT

//draw current key point
X_DOT points[keyPoint].x, points[keyPoint].y, points[keyPoint].z,10, RGB(255,0,255) //10=size of keypoint: change as required


BuildSplineArray()


//draw all spline points
FOR i = 0 TO LEN(splines)-1
X_DOT splines[i].x, splines[i].y, splines[i].z, 1, RGB(180,180,180)
NEXT

//Screen instructions
X_MAKE2D
PRINT "F1: Toggle help", 5,5, RGB(200,200,200)
IF help = 1
PRINT "LEFT ARROW: Rotate Left", 5,25,RGB(200,200,200)
PRINT "RIGHT ARROW: Rotate Right", 5,45,RGB(200,200,200)
PRINT "UP ARROW: Rotate Up", 5,65,RGB(200,200,200)
PRINT "DOWN ARROW: Rotate Down", 5,85,RGB(200,200,200)
PRINT "1: Add Key Point", 5,105,RGB(200,200,200)
PRINT "2: Remove Key Point", 5,125,RGB(200,200,200)
PRINT "TAB: Next Key Point",5,145,RGB(200,200,200)
PRINT "W: Move Z+", 5,165,RGB(200,200,200)
PRINT "S: Move Z-",5,185,RGB(200,200,200)
PRINT "A: Move X-",5,205,RGB(200,200,200)
PRINT "D: Move X+",5,225,RGB(200,200,200)
PRINT "R: Move Y+",5,245,RGB(200,200,200)
PRINT "F: Move Y-",5,265,RGB(200,200,200)


ENDIF
PRINT "Number of Key Points: "+numPoints, 5,580, RGB(200,200,200)
SHOWSCREEN
WEND

FUNCTION SetupPoints:
LOCAL point AS POINT
point.x = -extent/2; point.y=0; point.z=0; DIMPUSH points[],point
point.x = 0; point.y=-extent/2; point.z=0; DIMPUSH points[],point
point.x = extent/2; point.y=0; point.z=0; DIMPUSH points[],point
point.x = 0; point.y=extent/2; point.z=0; DIMPUSH points[],point
ENDFUNCTION



FUNCTION BuildSplineArray:
LOCAL i,j,n,m,mhf,tx,ty,tz
LOCAL spline AS POINT

IF CALC THEN RETURN
CALC = TRUE

//Empty the spline array for new spline points
FOR i = 0 TO LEN(splines)-1
DIMDEL splines[],0
NEXT

//Empty the waypoint array for new waypoints
FOR i = 0 TO LEN(waypoints)-1
DIMDEL waypoints[],0
NEXT

//build new spline array
i= -1
WHILE TRUE
//DEBUG i + "\n"
i = i+1
IF i <= numPoints - 3
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[i+1].x, points[i+1].y, points[i+1].z, _
                  points[i+2].x, points[i+2].y, points[i+2].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints -2
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[i+1].x, points[i+1].y, points[i+1].z, _
                  points[0].x, points[0].y, points[0].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints -1
QuadraticBezier3d(points[i].x,   points[i].y,   points[i].z, _
                  points[0].x, points[0].y, points[0].z, _
                  points[1].x, points[1].y, points[1].z, _
                  maxPoints)
FOR j = 0 TO LEN(QuadraticBezierArray3d) -1
spline.x = QuadraticBezierArray3d[j][0]
spline.y = QuadraticBezierArray3d[j][1]
spline.z = QuadraticBezierArray3d[j][2]
DIMPUSH splines[],spline
NEXT
ENDIF

IF i = numPoints THEN BREAK
WEND

ENDFUNCTION


The full project is attached as well



[attachment deleted by admin]
#4
In the Project > Options dialog: What does MULTISAMPLE do? 
#5
Hi, me again, but this time with an Android question.
I'm getting closer to my GLBasic goals, and decided to detour to test on Android. I have all the SDK's and Java stuff set up.
The problem however is I can get the APK copied, installed and run the app on my device, but I do not have the media files or folder available to the app. I checked inside the .apk and it's also not in there. The app runs great on my device, except it has no media files to support it.
Do I have to do something manually in order to get the media folder and files onto the device?
#6
After a lot of fun and headaches with the MEM* commands, some of which still need to be resolved, I finally got the basic ideas for a painting program to work.
There's still a lot of work to do, but this should serve as a sample of having some simple "painting" fun

Left mouse button to paint
Right mouse button to reset

Images uses in this sample are attached.

Code (glbasic) Select
// --------------------------------- //
// Project: mem-paint-test
// --------------------------------- //


SETCURRENTDIR("Media")


LOCAL PX1%[], PX2%[]
LOCAL x,y,r,c,i,mx,my,mbl,mbr,rr,cc
LOCAL cr,cg,cb,ca
LOCAL argb%


CREATESCREEN 1,1,640,480
CREATESCREEN 2,2,40,40
CREATESCREEN 3,3,640,480

LOADSPRITE "catndog1.png",1
LOADSPRITE "ball.png",2


WHILE TRUE

//get mouse state
MOUSESTATE mx,my,mbl,mbr

//reset image - should build load safety timer here.. but its a test anyway.
IF mbr = 1 THEN LOADSPRITE "catndog1.png",1


//check that the mouse right and bottom are on the screen
//.....else the arrays fall over

IF mx+39 < 640 AND my+39 < 480
//get the background
SPRITE2MEM (PX1[],1)

//get paintbrush 
SPRITE2MEM (PX2[],2)

//paste brush onto background
IF mbl = 1
rr = -1
FOR r = my TO my + 39   //for each row
rr = rr + 1
cc = -1
FOR c = mx TO mx + 39  //for each column
cc = cc + 1

argb = PX2[cc+rr*40]
cr = bAND(argb, 0xff)
cg = bAND(ASR(argb,8), 0xff)
cb = bAND(ASR(argb,16), 0xff)
ca = bAND(ASR(argb,24), 0xff)

IF ca <> 0
PX1[c+r*640] = argb
ENDIF

NEXT
NEXT
MEM2SPRITE (PX1[],1,640,480)

ENDIF
ENDIF     //mouse in screen

//START DRAWING from here
USESCREEN -1

//dump background
DRAWSPRITE 1,0,0


//display paintbrush
DRAWSPRITE 2,mx,my

PRINT "Right Mouse button to reset", 5,450
SHOWSCREEN
WEND


[attachment deleted by admin]
#7
Hi again,

This time it's my turn to ask a MEM2* question, but more to ask if anyone can see what I am wrong in my code.
This is my first attempt at using the MEM stuff, to see if I can actually use a dirty rectangle method in painting with a "brush". It's easy with drawsprite to a buffered screen, but the MEM thing is hopefully the start of a more complex  bit based process for painting.

I would really appreciate some educate eyes to see where I am messing up in my code. It's probably something very noobish, so please be gentle with that stick :)

Code (glbasic) Select
// --------------------------------- //
// Project: mem2mem-paint-test
// --------------------------------- //

//we define our variables here
GLOBAL x,y,i,r,i, mx,my,mlb,mrb,c,cc,rr
GLOBAL brush%[], bground%[], dirty%[]


//we start with a white image to paint on - we stick to 640x480 with this test
CREATESCREEN 30, 99, 640, 480    //screen 30, sprite 99, our work area

//we now use our own screen to make our work area white
USESCREEN 30
DRAWRECT 0,0,640,480, RGB(255,255,255)

//we set up a new screen for a paintbrush image
CREATESCREEN 31, 100, 20, 20   //screen 31, sprite 100, brush size 20x20

//we switch to our paintbrush screen to create the brush
USESCREEN 31

//we use math to draw in circles
FOR r = 1 TO 10                                 //for radius 1 to 10. Half width of our brush = radius
FOR i = 0 TO 360                            //all around the compas
x = SIN(i)*r                            //1st part of a circle formula
y = COS(i)*r                            //2nd part of a circle formula
SETPIXEL x+10,y+10,RGB(100,100,100)     //0,0 is top left corner, so we offset drawing to middle of image
NEXT
NEXT

//our main game loop
WHILE TRUE

//we get the mouse state
MOUSESTATE mx,my,mlb,mrb

//if the left button is down, we MEM our brush onto the canvas
IF mlb =1 THEN drawBrush()


//we ensure that all final drawings go to the real screen
USESCREEN -1

//we draw our work area sprite onto the real screen
DRAWSPRITE 99, 0, 0

//use the brush as a mouse pointer
DRAWSPRITE 100,mx,my

SHOWSCREEN
WEND


FUNCTION drawBrush:   //we could use parameter, but for this test we use globals
LOCAL x = mx-9     //mouse x less half the brush width + center pixel
LOCAL y = my-9     //mouse y less half the brush height + center pixel
LOCAL w = x+19     //width of the brush less 1
LOCAL h = y+19     //height of the brush less 1
LOCAL r%,g%,b%,a%
LOCAL BGabgr%      //Background alpha, red, green, blue . .that's why it has a funny name
LOCAL DIRTYabgr%, BRUSHabgr%
LOCAL rr,yy

//grab the background work area
SPRITE2MEM(bground%[], 99)

//grab the brush
SPRITE2MEM(brush%[], 100)

//build the dirty rectangle
rr = -1 //inner rows
cc = -1                                                                          //inner columns
FOR r = y TO h        //for each row
    rr = rr + 1 //for each inner row
    cc = -1                                                                         //reset inner column for new row
FOR c = x TO w    //for each column
    cc = cc + 1 //for each inner column
BGabgr% = bground%[c + r*20]             //get a piece of our drawing buffer
DIRTYabgr% = BGabgr% //get the buffer into the dirty rectangle
BRUSHabgr% = brush%[cc + rr*20]          //get the brush
BGabgr% = bOR(DIRTYabgr%,BRUSHabgr%)    //add the brush to the diry rectangle
bground%[c + r*20] = BGabgr%                    //rebuild background from the rectangle
NEXT
NEXT

//Replace background with changes
MEM2SPRITE(bground%[], 99, 640, 480)

ENDFUNCTION


#8
Hi again,
I was curious to see if I would be able to make small images to be used for paintbrushes in a paint program that I have in mind. It's straight forward to make an image with a 2D painter, but wanted to try to dynamically make all kinds of "paint brushes", so that I do not have hundreds of brush images to clutter the place.

Background:
I wrote a little program that uses SPRITE2MEM and MEM2SPRITE just to see how things would work, since the documentation warns that GETPIXEL can be very slow. The program uses a linear-move (linear-swap without comparing) concept to play around with the pixels. It's a very crude program, but it's the speed of the program that has me a little concerned. The idea is to use a paintbrush image and mix it with a different image on another "screen/buffer" in order to get all sorts of fun filter brush effects.

Code (glbasic) Select
// --------------------------------- //
// Project: spritememToy
// --------------------------------- //

LOCAL pxl%[]
LOCAL res
LOCAL w
LOCAL h
LOCAL x
LOCAL y
LOCAL sw
LOCAL sh
LOCAL barrel%
LOCAL i
LOCAL offs1, offs2

LOADSPRITE "prettyImage.png",0
GETSPRITESIZE 0,w,h
GETSCREENSIZE sw,sh
res = SPRITE2MEM(pxl%[], 0)

WHILE 1
FOR y = 0 TO h-1
FOR i = 0 TO w-1
offs1 = (w/2 + i) + (y*h)
offs2 = (w/2 + i+1) +(y*h)
barrel% = pxl%[offs1]
pxl%[offs1] = pxl%[offs2]
pxl%[offs2] = barrel%
NEXT
MEM2SPRITE (pxl%[], 0, w, h)
NEXT
DRAWSPRITE 0, sw/2-w/2, sh/2-h/2

PRINT w+" "+h, 10,10
SHOWSCREEN
WEND


Question:
There are nothing wrong with the MEM functions, but they may be too slow for what I have in mind. Are MEM functions the fastest way to manipulate pixels in an image, or is there a faster way?  I could go the INLINE route, but then it moves out of the realm of what I want to teach the kids in my computer lessons. I hope there is a solution, else I may have to leave out this fun little exercise in my course.
My program itself may also be the problem, and it is perhaps just too crude for the mission.

Edit: I've included the image I used for my tests.

[attachment deleted by admin]
#9
This little project was inspired when I discovered that the print does not zoom very well. This solution uses a large font file, and allows you to zoom it smaller for different sizes.

The left alignment needs a little work, but I'll leave that to the experts to play with. Note that this does not use the built in PRINT command, but duplicates what it does.

Code (glbasic) Select

TYPE _PRINTX
chr []
fontID
base
border = 2   //font border if used
fw = 64 + self.border    //font width
fh = 72 + self.border    //font height
count = 15

FUNCTION Init: font$
LOCAL i, j, c=-1, x,y
self.fontID = RND(1000)+1000
self.base = RND(10000)+2000
LOADSPRITE font$, self.fontID
FOR j = 0 TO 15  //change this to 31 to include high ascii values
FOR i = 0 TO 15
c = c + 1
x = i * self.fw
y = j * self.fh
CLEARSCREEN
DRAWSPRITE self.fontID, -x,-y
GRABSPRITE self.base + c, 0,0, self.fw, self.fh 
DIMPUSH self.chr[], self.base + c
NEXT
NEXT
CLEARSCREEN
ENDFUNCTION


FUNCTION _print: text$, x, y, scale#
LOCAL i,c, s$
FOR i = 0 TO LEN(text$)-1
s$ = MID$(text$,i,1)
c = ASC(s$)
ZOOMSPRITE self.chr[c], x + (i * self.fw *scale#), y, scale#, scale#
NEXT
ENDFUNCTION

ENDTYPE



LOCAL font1 AS _PRINTX   //define your own font object

font1.Init("arial72.png")  //initialize the font here

font1._print ("AbCdEfG 123", 0, 0, 0.2) 
font1._print ("Hello world", 0, 20, 0.2)
font1._print ("!@#$%^&*()_+", 0, 40, 0.3)
font1._print ("Is it a bird, is it a plane? No it's Super-GLBasic", 0 ,60, 0.18)
font1._print ("Eat your food to grow", 0, 80, 0.4)
font1._print ("even bigger", 0, 110, 0.6)
font1._print ("and bigger", 0, 140, 0.8)
font1._print ("Yum !", 30, 200, 1.5)
font1._print ("...oooOOOoooooo...", 20, 300, 0.5)

SHOWSCREEN
MOUSEWAIT


[attachment deleted by admin]
#10
Hi, I'm back to ask another silly question.

As I am looking at using GLBasic for some time to come, I need to know what version of the GCC compiler is used in Version 11.261 of GLBasic.
In Version 10.283 of GLBasic the GCC compiler is version 3.4.5
Why I need to know this is to make sure the the MingW (static) libraries, not dlls, I build are compatible with GLBasic in the future. This is only for Windows, the rest of the OS's are of no concern to me.

So if anyone can find the time, I would really appreciate some feedback on this.
In order to find the GCC version, one needs to open a command window, and then in the GLBasic\Compiler\platform\Win32\Bin folder run the following command:  gcc -dumpversion

Thanks in advance.
#11
Hi again,
This time I have success. I looked into this wrapper thing, and this is the key to being able to call a dll made in GLBasic. It works and I am elated.
I can't thank you guys enough for your input, this is really totally awesome, and I will be able to build on from here.

Just to share what I have done, so that others may benefit from my effort, and the efforts of all the dll boffs that have posted their stuff on this forum, for people like me to learn from.

The dll source code. This is a project on it's own, and the resulting .dll must be copied into the calling .exe projects ".app" folder.

Code (glbasic) Select

FUNCTION addem#: number1#, number2#
   LOCAL result#
   result# = number1# + number2#
   RETURN result#
ENDFUNCTION

EXPORT addem


The wrapper source code and the actual program that uses it. It is as Hemlos mentioned, this has to be included in the same project as the calling exe in order for it to work.

Wrapper source

Code (glbasic) Select
TYPE GLBDLLWRAPPER

INLINE
   DECLARE_C_ALIAS(addit, "littledll.dll", "addem", (float, float), float);
ENDINLINE

FUNCTION addem#: num1#, num2#
LOCAL res#
INLINE
if(addit){
PRINT ("DLL FOUND", 20,60);
res = addit(num1, num2);
}else{
PRINT ("DLL NOT FOUND", 20,60);
}
ENDINLINE
RETURN res#
ENDFUNCTION

ENDTYPE


Calling program source code

Code (glbasic) Select
GLOBAL num1#, num2#, res#
GLOBAL mydll AS GLBDLLWRAPPER

num1# = 123.45
num2# = 234.21
res# = 101.01

res# = mydll.addem(num1#, num2#)

PRINT res#, 20,80
SHOWSCREEN
MOUSEWAIT


I had a lot of reading to do to see how others made their wrappers, and it seems that to embed it into a TYPE is the easiest and best way to go, That's how they seem to do it. And it works perfectly. With the wrapper, the compiled exe can now see the dll, and load it at runtime as is should. And the dll is written in GLBasic, which is what i was after all the time. And it works.

Thanks again for all your help guys. You are the Bomb.

The working exe and dll, as well as their projects are attached to show that it really does work

PS: Edited some typos. :D

[attachment deleted by admin]
#12
Hi again, another question I need help with.

I've written a simple dll in GLBasic, and it works great. I can pass it a float, and get a changed float back

Code (glbasic) Select
FUNCTION func1#: param1#
   LOCAL x#
   x# = param1# + 5
   return x#
ENDFUNCTION

EXPORT func1


But my question has to do with using an array of float as a parameter.

How would I pass the array of float as a parameter, and be able to change the array contents inside the dll, and then get the changed values back into the calling GLB program?

A "do it yourself" answer is really of no use to anyone, and is actually very insulting.
http://www.glbasic.com/forum/index.php?topic=8831.msg75123#msg75123

Since I don't know how this is done, that is why I am asking.
#13
Is it possible to pass a "type" variable as a parameter to a function?
#14
I seem to have a problem with DRAWLINE not being able to draw to a sprite created with CREATESCREEN. The DRAWRECT does work. So I am wondering if this a bug, or am I doing something wrong?

Code with the problem
Code (glbasic) Select

// Screen 0, Sprite 13
CREATESCREEN 0, 13, 256, 256

// Use screen for all output
USESCREEN 0

PRINT "Offscreen", 0,0
ALPHAMODE 0.8
DRAWRECT 254,0,5, 256, RGB(0,250,0)    // <<---- This works
DRAWLINE 256,256,512,256, RGB(0,250,0) // <<---- Does not work
   
// Switch back to the window
USESCREEN -1

// Draw the screen
DRAWSPRITE 13, 0, 0

SHOWSCREEN
MOUSEWAIT
#15
I can include "c" header files within an INCLUDE statement. However, is it possible to link to an external (gcc  .a / .o) library, in order to use that library's functions in my compiled project?  If possible, how?
Thanks in advance.
#16
Hi, I'm still kinda new to this, but it seems that GLBasic converts the Basic code into c++ code. So i've read. Is it in any way possible to see the c++ code that gets produced ?
Thanks.
#17
Here's an extended drawing library that adds a few extra drawing primitives.
Objects include line, lineto, rectangle, filledrectangle, circle, filledcircle, oval, filledoval. pixel
Just comment out the "test" function, add the file to your project, and call the required functions. Use the test function as and example
Setting _drawcolor will set the color for all subsequent drawing calls
line and pixel save the last x,y location - for using lineto function.

Code (glbasic) Select
// --------------------------------- //
// Project: DrawingObjects

test()

TYPE _DSTORE
x
y
color
ENDTYPE

GLOBAL _dstore AS _DSTORE; _dstore.x=0; _dstore.y=0; _dstore.color = RGB(255,255,255)

FUNCTION _drawcolor: r,g,b
_dstore.color = RGB(r,g,b)
ENDFUNCTION

FUNCTION _line: x1, y1, x2, y2
DRAWLINE x1, y1, x2, y2, _dstore.color
_dstore.x = x2
_dstore.y = y2
ENDFUNCTION

FUNCTION _lineto: x,y
DRAWLINE _dstore.x, _dstore.y, x, y, _dstore.color
_dstore.x = x
_dstore.y = y
ENDFUNCTION

FUNCTION _rectangle: x,y,w,h
_line(x,y,x+w-1,y)
_lineto(x+w-1,y+h-1)
_lineto(x,y+h-1)
_lineto(x,y)
ENDFUNCTION

FUNCTION _filledrectangle: x, y, w, h
DRAWRECT x, y, w, h, _dstore.color
ENDFUNCTION

FUNCTION _pixel: x,y
SETPIXEL x,y,_dstore.color
_dstore.x = x
_dstore.y = y
ENDFUNCTION

FUNCTION _circle: x,y,r
_pixel((SIN(0)*r)+x , (COS(0)*r)+y)
FOR i = 1 TO 360 STEP 10
_lineto( (SIN(i)*r)+x , (COS(i)*r)+y)
NEXT
_lineto( (SIN(0)*r)+x , (COS(0)*r)+y)
ENDFUNCTION

FUNCTION _filledcircle: x,y,r
LOCAL lx,rx,yy
FOR i = 0 TO 180 STEP 0.5
lx = (SIN(i)*r)+x
rx = (SIN(360-i)*r)+x
yy = (COS(i)*r)+y
_line(lx,yy,rx,yy)
NEXT
ENDFUNCTION

FUNCTION _oval: x,y,w,h
_pixel((SIN(0)*w/2)+x , (COS(0)*h/2)+y)
FOR i = 1 TO 360 STEP 10
_lineto( (SIN(i)*w/2)+x , (COS(i)*h/2)+y)
NEXT
_lineto( (SIN(0)*w/2)+x , (COS(0)*h/2)+y)
ENDFUNCTION

FUNCTION _filledoval: x,y,w,h
LOCAL lx,rx,yy
FOR i = 0 TO 180 STEP 0.5
lx = (SIN(i)*w/2)+x
rx = (SIN(360-i)*w/2)+x
yy = (COS(i)*h/2)+y
_line(lx,yy,rx,yy)
NEXT
ENDFUNCTION

FUNCTION test:
WHILE TRUE
_drawcolor(200,100,50)
_line(300,50,200,100)
_lineto(200,200)
_lineto(400,200)
_lineto(400,100)
_lineto(300,50)
_filledrectangle(140,240,200,100)
_rectangle(400,250,100,50)
_pixel(500,100)
_drawcolor(255,40,100)
_circle(500,100,50)
_filledcircle(500,400,60)
_oval(500,100,90,50)
_drawcolor(0,50,255)
_filledoval(500,400,50,95)

SHOWSCREEN
WEND
ENDFUNCTION