Posted: 10th Feb 2019 21:16
A bare bones 3D Placement editor EDITED
+ Code Snippet
// Project: 3D Placement Editor 
// Created: 2019-02-11

// show all errors
SetErrorMode(2)
 
#constant screenwidth=1024
#constant screenheight=768
#constant fullscreen=0
#constant screenrate=0
#constant KEY_LEFT         37
#constant KEY_UP           38
#constant KEY_RIGHT        39
#constant KEY_DOWN         40
#constant KEY_W            87
#constant KEY_A            65
#constant KEY_S            83
#constant KEY_Z            90
#constant KEY_L            76
#constant KEY_F1           112
#constant KEY_F2           113

#constant KEY_LESSTHAN 	   188
#constant KEY_GREATERTHAN  190
	
#constant KEY_HOME         36
#constant KEY_PLUS         107
#constant KEY_SUBTRACT     109
#constant KEY_SHIFT        16

//change these values to ammounts you find useful
#constant moveAmmount      0.05
#constant rotateAmmount    0.05
#constant scaleAmmount     0.1

type _object
    ID as integer
    imageID as integer
    scale as float
    name as string
    imageName as string
endtype

type point
	x	as float
	y	as float
	z	as float
endtype

type camera
	dolly	as integer
	camera	as integer
	offset  as point 
	last	as point
	angle	as point
endtype


camera 		as camera


// set window properties
SetWindowTitle( "3D Placement Editor" )
SetWindowSize( screenwidth, screenheight, fullscreen )
SetWindowAllowResize( 1 ) // allow the user to resize the window
 
// set display properties
SetVirtualResolution( screenwidth, screenheight ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( screenrate, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

camera.dolly = CreateObjectBox(1, 1, 1)
SetObjectVisible(camera.dolly, 0)
camera.camera = CreateObjectBox(1, 1, 1)
SetObjectVisible(camera.camera, 0)
camera.angle.x = 0

FixObjectToObject(camera.camera, camera.dolly)
MoveObjectLocalZ(camera.camera, -20)
RotateObjectLocalX(camera.dolly, camera.angle.x)


objects as _object[]
global current as integer
current=-1:saveFlag=0
SetCameraPosition(1,0,10,-20 ) 
do
	if GetRawKeyPressed(KEY_L)
		DeleteAllObjects()
		DeleteAllImages()
		for num = objects.length to 0 step-1
			objects.remove(num)
		next num	
		current=-1:saveFlag=1
		loadObjects(objects)
		Message(left(ret$,len(ret$)-(len(objects[current].name)+1))+" test.data loaded")
	endif
	
    if GetRawKeyPressed(KEY_F1)
		object as _object 
		ret$=ChooseRawFile("*.obj;*.3ds",1)
		if ret$<>""
             object.ID=loadObject("raw:"+ret$)
             count=1
             for num = 1 to len(ret$)
				if Mid(ret$,num,1)="\" then inc count 
			 next num	 
             object.name=GetStringToken( ret$, "\", count )
			 ret$=ChooseRawFile("*.jpg;*.png",1)
		     if ret$<>""
				count=1
				for num = 1 to len(ret$)
					if Mid(ret$,num,1)="\" then inc count 
				next num	 
				object.ImageName=GetStringToken( ret$, "\", count )
				object.imageID=loadImage("raw:"+ret$)
				SetObjectImage(object.ID,object.imageID,0)
			 endif
			 object.scale=1:saveFlag=1
			 objects.insert(object)
			 inc current
        endif
	endif	
	
	if GetRawKeyPressed(KEY_F2) and saveFlag=1
		if current>=0
			saveData(objects,"raw:"+left(ret$,len(ret$)-(len(objects[current].name)+1))+"test.data")
			Message("test.data saved to "+left(ret$,len(ret$)-(len(objects[current].name)+1)))
		endif
	endif
	if current>=0
	Print(left(ret$,len(ret$)-(len(objects[current].name)+1))+"test.data")
	endif
	//camera movement commands
	if GetRawKeyState(KEY_SHIFT) and GetRawKeyState(KEY_W) 
		MoveObjectLocalY(camera.camera,moveAmmount)
		//SetCameraPosition(1,getCameraX(1),getCameraY(1)+1,getCameraZ(1))
	elseif GetRawKeyState(KEY_W)
		MoveObjectLocalZ(camera.camera,moveAmmount)
		//SetCameraPosition(1,getCameraX(1),getCameraY(1),getCameraZ(1)+1)
	endif
	
	if GetRawKeyState(KEY_A)
		MoveObjectLocalX(camera.camera,-moveAmmount)
		//SetCameraPosition(1,getCameraX(1)-1,getCameraY(1),getCameraZ(1))
	endif
	
	if GetRawKeyState(KEY_S)
		MoveObjectLocalX(camera.camera,moveAmmount)
		//SetCameraPosition(1,getCameraX(1)+1,getCameraY(1),getCameraZ(1))
	endif
	
	if GetRawKeyState(KEY_SHIFT) and GetRawKeyState(KEY_Z) 
		MoveObjectLocalY(camera.camera,-moveAmmount)
		//SetCameraPosition(1,getCameraX(1),getCameraY(1)-1,getCameraZ(1))
	elseif GetRawKeyState(KEY_Z)
		MoveObjectLocalZ(camera.camera, -moveAmmount)
		//SetCameraPosition(1,getCameraX(1),getCameraY(1),getCameraZ(1)-1)
	endif

	
	if current>=0
		//object movement commands
		if GetRawKeyState(KEY_SHIFT) and GetRawKeyState(KEY_UP) 
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID),getObjectY(objects[current].ID)+moveAmmount,getObjectZ(objects[current].ID))
		elseif GetRawKeyState(KEY_UP)
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID),getObjectY(objects[current].ID),getObjectZ(objects[current].ID)+moveAmmount)
		endif
	
		if GetRawKeyState(KEY_LEFT)
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID)-moveAmmount,getObjectY(objects[current].ID),getObjectZ(objects[current].ID))
		endif
	
		if GetRawKeyState(KEY_RIGHT)
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID)+moveAmmount,getObjectY(objects[current].ID),getObjectZ(objects[current].ID))
		endif
	
		if GetRawKeyState(KEY_SHIFT) and GetRawKeyState(KEY_DOWN) 
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID),getObjectY(objects[current].ID)-moveAmmount,getObjectZ(objects[current].ID))
		elseif GetRawKeyState(KEY_DOWN)
			SetObjectPosition(objects[current].ID,getObjectX(objects[current].ID),getObjectY(objects[current].ID),getObjectZ(objects[current].ID)-moveAmmount)
		endif
		
		if GetRawKeyState(KEY_GREATERTHAN)
			RotateObjectLocalY(objects[current].ID,rotateAmmount)
		endif
		if GetRawKeyState(KEY_LESSTHAN)
			RotateObjectLocalY(objects[current].ID,-rotateAmmount)	
		endif
		
		if GetRawKeyPressed(KEY_PLUS)
			objects[current].scale=objects[current].scale+scaleAmmount
			SetObjectScale(objects[current].ID,objects[current].scale,objects[current].scale,objects[current].scale)
		endif
		if GetRawKeyPressed(KEY_SUBTRACT)
			objects[current].scale=objects[current].scale-scaleAmmount
			SetObjectScale(objects[current].ID,objects[current].scale,objects[current].scale,objects[current].scale)
		endif

		print("Name ="+(objects[current].name))
		print("Scale ="+str(objects[current].scale))
		print("Angle X#="+str(GetObjectAngleX(objects[current].ID)))
		print("Angle Y#="+str(GetObjectAngleY(objects[current].ID)))
		print("Angle Z#="+str(GetObjectAngleZ(objects[current].ID)))
		print("Pos X#="+str(GetObjectX(objects[current].ID)))
		print("Pos Y#="+str(GetObjectY(objects[current].ID)))
		print("Pos Z#="+str(GetObjectZ(objects[current].ID)))
	endif
	Gimbal(camera)
	print("CAMERA VALUES")
	print("cam x="+str(GetCameraX(1)))
	print("cam y="+str(GetCameraY(1)))
	print("cam z="+str(GetCameraZ(1)))
	print("CAMERA ANGLES")
	print("Dolly ("+str(Round(GetObjectAngleX(camera.dolly)))+","+str(Round(GetObjectAngleY(camera.dolly)))+","+str(Round(GetObjectAngleZ(camera.dolly)))+")")
    print("Camera ("+str(Round(GetObjectWorldAngleX(camera.camera)))+","+str(Round(GetObjectWorldAngleY(camera.camera)))+","+str(Round(GetObjectWorldAngleZ(camera.camera)))+")")	
    print("Internal ("+str(Round(camera.angle.x))+","+str(Round(camera.angle.y))+","+str(Round(camera.angle.z))+")")	
    Print( ScreenFPS() )
    Sync()
loop

function saveData(objects as _object[],filename$ as string)
	fw = OpenToWrite(filename$)
	For num=0 to objects.length
		writeline(fw,objects[num].name+" "+objects[num].imageName+" "+str(objects[num].scale)+" "+str(GetObjectAngleX(objects[num].ID))+" "+str(GetObjectAngleY(objects[num].ID))+" "+str(GetObjectAngleZ(objects[num].ID))+" "+str(GetObjectX(objects[num].ID))+" "+str(GetObjectY(objects[num].ID))+" "+str(GetObjectZ(objects[num].ID)))
	next num
	CloseFile ( fw ) 
endfunction	

function loadObjects(objects ref as _object[])
	local myObject as _object
	fr=OpenToRead("test.data")
	myString$=ReadLine(fr)
	while FileEOF(fr)=0
		temp$=GetStringToken(myString$," ",1)
		myObject.ID=LoadObject(temp$)
		myObject.name=temp$
		temp$=GetStringToken(myString$," ",2)
		myObject.imageID=LoadImage(temp$)
		myObject.imageName=temp$
		SetObjectImage(myObject.ID,myObject.imageID,0)
		//SetObjectScale(myObject.ID,ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)))
		SetObjectRotation(myObject.ID,ValFloat(GetStringToken(myString$," ",4)),ValFloat(GetStringToken(myString$," ",5)),ValFloat(GetStringToken(myString$," ",6)))
		SetObjectPosition(myObject.ID,ValFloat(GetStringToken(myString$," ",7)),ValFloat(GetStringToken(myString$," ",8)),ValFloat(GetStringToken(myString$," ",9)))
		objects.insert(myObject):inc current
		myString$=ReadLine(fr)
	endwhile
	closefile(fr)
endfunction	  

function    Gimbal(camera ref as camera)
    d       as point
    v       as float
    a       as float
    p		as point
    dist	as float
              
    if GetPointerPressed() = 1
        camera.last.x = GetPointerX()
        camera.last.y = GetPointerY()        
    endif   
	
	if GetRawMouseRightPressed()
		hit=checkCollision()
		if hit<>0 
			camera.offset.x=GetObjectWorldX(hit)
			camera.offset.y=GetObjectworldY(hit)
			camera.offset.z=GetObjectWorldZ(hit)
		else
			camera.offset.x=0
			camera.offset.y=0
			camera.offset.z=0	
		endif
	endif
	
    if GetPointerState() = 1 
	

	p.y = GetPointerY() - camera.last.y
        inc camera.angle.x, p.y 
        
        p.x = GetPointerX() - camera.last.x
        inc camera.angle.y, p.x
    
	camera.last.x = GetPointerX()
        camera.last.y = GetPointerY()        
    endif
 
 
   SetObjectRotation(camera.dolly, camera.angle.x, camera.angle.y, 0)
   SetCameraPosition(1, GetObjectWorldX(camera.camera)+camera.offset.x, GetObjectWorldY(camera.camera)+camera.offset.y, GetObjectWorldZ(camera.camera)+camera.offset.z)
   SetCameraRotation(1, camera.angle.x, camera.angle.y, 0)
	
		
endfunction

function checkCollision()
     // get the position of the pointer (mouse)
     pointer_x = GetPointerX()
     pointer_y = GetPointerY()
 
     // get the x, y and z unit vectors based on the pointer position
     unit_x# = Get3DVectorXFromScreen(pointer_x,pointer_y)
     unit_y# = Get3DVectorYFromScreen(pointer_x,pointer_y)
     unit_z# = Get3DVectorZFromScreen(pointer_x,pointer_y)
 
     // calculate the start of the ray cast, which is the unit vector + the camera position
     start_x# = unit_x# + 0
     start_y# = unit_y# + 10
     start_z# = unit_z# - 20
 
     // calculate the end of the vector, which is the unit vector multiplied by the length of the ray cast and then add the camera position to it
     end_x# = 800*unit_x# + 0
     end_y# = 800*unit_y# + 10
     end_z# = 800*unit_z# - 20
 
     // determine which object has been hit
     object_hit = ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)
endfunction object_hit


Keys
F1 load an object and then an image to assign to it
f2 save test.data
L to delete all and load objects as set in test.data
<, > rotate object
+,- scale object
w,a,s,d,shift move camera
Clicking and holding mouse rotates mouse around its position
Right Clicking an Object moves camera to concentrate on that object (ie so it would rotate around that object)
arrow keys ,shift move current object

Function
creates a test.data file that can be later used in your program that can load a series of objects
saving there name, scale, xangle, yangle, zangle, xpos ypos, and zpos

Note: It will save the file test.data in the same directory as the last object loaded

Using the data You could then use this function in your program to load position rotate etc your objects
+ Code Snippet
function loadObjects(objects ref as _object[])
	local myObject as _object
	fr=OpenToRead("test.data")
	myString$=ReadLine(fr)
	while FileEOF(fr)=0
		temp$=GetStringToken(myString$," ",1)
		myObject.ID=LoadObject(temp$)
		myObject.name=temp$
		temp$=GetStringToken(myString$," ",2)
		myObject.imageID=LoadImage(temp$)
		myObject.imageName=temp$
		SetObjectImage(myObject.ID,myObject.imageID,0)
		//SetObjectScale(myObject.ID,ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)))
		SetObjectRotation(myObject.ID,ValFloat(GetStringToken(myString$," ",4)),ValFloat(GetStringToken(myString$," ",5)),ValFloat(GetStringToken(myString$," ",6)))
		SetObjectPosition(myObject.ID,ValFloat(GetStringToken(myString$," ",7)),ValFloat(GetStringToken(myString$," ",8)),ValFloat(GetStringToken(myString$," ",9)))
		objects.insert(myObject):inc current
		myString$=ReadLine(fr)
	endwhile
	closefile(fr)
endfunction	
Posted: 11th Feb 2019 12:43
Hi fubarpk

Nice programm . I tested loading and placing two objects pressing f1 and f2 ...then I try to load and couldn't fine file ...I just checked every thing in media folder and realize that the file created was "tetest.data" ....it should be "test.data" instead of tetest.data so it was easy to find where was the error ...in line 96 , instead of :

saveData(objects,"raw:"+left(ret$,len(ret$)-(len(objects[current].name)+1))+"test.data")
... I had to write

saveData(objects,"raw:"+left(ret$,len(ret$)-(len(objects[current].name)+3))+"test.data")



with this change, I can now save both objects and load them again pressing L key
When I load a third object and save it again it just is not there...
I realize aswell that when we scale object and save, ....when load it, the object doesn't keep the scaling... I think that should be easy to mend just setting object pivot ...and setting object permanent scale.
I could with object pivot but couldn't with setobjectscalepermanent .

It is not a criticism but rather an observation any way with some adjustements is a good snippet

Edit.
When I place the object and try to save again I have a path error .

Posted: 11th Feb 2019 13:07
Thanks Chafari
just something I threw together out of necessity

saveData(objects,"raw:"+left(ret$,len(ret$)-(len(objects[current].name)+3))+"test.data")

strange cos 1 works well for me the idea it just determines the raw path by subtracting the length of the last object name as the lengths begin at zero I needed to add one
I seem to recall you saying something about using Vista or something that may be the issue not really sure

When I load a third object and save it again it just is not there...

not sure it may be the array objects will look later I thought if I deleted everything in the array and if I set current to -1 it would work

I realize aswell that when we scale object and save, ....when load it, the object doesn't keep the scaling

the command is there in loadobjects just commented out
+ Code Snippet
//SetObjectScale(myObject.ID,ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)),ValFloat(GetStringToken(myString$," ",3)))


When I place the object and try to save again I have a path error .

I think that's because you have loaded with test.data and not loaded another object to get a new path to save to and test.data having a different extension
I should have a variable that sets it so as the file wont save again unless there is changes and perhaps a message displaying if saved or not

Hahahah its bound to have a few bugs I just whipped it up hoping it could be of help to me but thought ide share, it was painstaking trying to place the billboards in KrazyGrandPrix otherwise

EDITED the above code to only allow saves when there is changes and some message boxes so as can see whats happening
Posted: 13th Feb 2019 1:21
A Shatter-Sprite Routine
was experimenting with a shatter routine for 2D like I have used for 3D in the Past
could be used when you don't have an exploding sprite animation I guess. The 3D
version is much more effective
+ Code Snippet
// Project: ShatterSprite 
// Created: 2019-02-13

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "ShatterSprite" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

type _SprBlock
    OldID as integer
    ID as integer       //the id of the object
    imgID as integer
    xPos as integer
    yPos as integer
    xDirection as float 
    yDirection as float 
    timer as float
endtype

castleImg=loadImage("castle.png")
castleSpr=CreateSprite(castleImg)
SetSpritePosition(castleSpr,((GetDeviceWidth()/2)-(getImageWidth(castleImg)/2)),(getDeviceHeight()/2)-(GetImageHeight(castleImg)/2))

SprBlocks as _SprBlock[]
ShatterInit(castleSpr,CastleImg,SprBlocks)
flag=0
do
    print("Press space to shatter")
    if getRawKeyPressed(32) then flag=1
    if flag=1 then ShatterSprite(castleSpr,SprBlocks)
    if SprBlocks.length&lt;=0 then  SetSpriteVisible(castleSpr,1) 
    Print( ScreenFPS() )
    Sync()
loop

function ShatterInit(spr as integer,img as integer,SprBlocks ref as _SprBlock[])
	tempBlock as _SprBlock
	x#=GetSpriteX(spr):y#=getSpriteY(spr)
	maxX=GetImageWidth(img):maxY=GetImageHeight(img)
	ClearScreen()
	DrawSprite(spr)	
	render()
	for y=0 to maxY step MaxY/16
		for x=0 to maxX step maxX/16


			tempBlock.imgID=GetImage(x,y,x+(maxX/16),y+(maxY/16))
			SetImageTransparentColor(tempBlock.imgID,0,0,0)
			tempBlock.OldID=Spr
			tempBlock.ID=createSprite(tempBlock.imgID)
			SetSpriteVisible(tempBlock.ID,0)
			tempBlock.xPos=x
			tempBlock.yPos=y
			tempBlock.xDirection=random2(-2,2)
			tempBlock.yDirection=random2(-2,2)
			tempBlock.timer=timer()
			SprBlocks.insert(tempBlock)
		next x
	next y
endfunction	

function ShatterSprite(spr as integer,SprBlocks ref as _SprBlock[])
	SetSpriteVisible(spr,0)
	for num=0 to SprBlocks.length
		if SprBlocks[num].OldID=spr
			SprBlocks[num].xPos=SprBlocks[num].xPos+SprBlocks[num].xDirection
			SprBlocks[num].yPos=SprBlocks[num].yPos+SprBlocks[num].yDirection
			SetSpritePosition(SprBlocks[num].ID,SprBlocks[num].xPos,SprBlocks[num].yPos)	
			SetSpriteVisible(SprBlocks[num].ID,1)
		endif 
	next num
	
	for num=SprBlocks.length to 0 step -1
		if SprBlocks[num].OldID=spr
			if SprBlocks[num].timer+5&lt;timer()
				DeleteSprite(SprBlocks[num].ID)
				DeleteImage(SprBlocks[num].imgID)
				SprBlocks.remove(num)
			endif	 
		endif	
	next num
	
endfunction	

for this one I used the below image


PS: I think a shader could do the same effect nicer as what really needs to be done is have all pixels move outward in a circular way and could just have a larger
image than shown with allot of transparency to compensate and move each pixel outwards

Could possibly be improved with a memblock by reading each colour of an image from left to right top to bottom and writing that colour on the image one to the left and one above
for all pixels in the left quarter zone of the image. then repeated for all other quarters as needed. Curious how that will work may or may not try later as I think it may be slow

Experimenting with just two sprites and scaling them doesn't work anywhere near as well I prefer the top snippet ohwell lol
+ Code Snippet

// Project: ShatterSprite 
// Created: 2019-02-13

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "ShatterSprite" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

castleImg=loadImage("castle.png")
castleSpr=CreateSprite(castleImg)
blackSpr=CreateSprite(0)
SetSpriteColor(blackSpr,0,0,0,255)
SetSpriteSize(blackSpr,2,2)
SetSpritePositionByOffset(castleSpr,(GetDeviceWidth()/2),(getDeviceHeight()/2))
SetSpritePositionByOffset(blackSpr,(GetDeviceWidth()/2),(getDeviceHeight()/2))
flag=0

SetSpriteDepth(castleSpr,10)
SetSpriteDepth(blackSpr,9)

do
    print("Press space to shatter")
    if getRawKeyPressed(32) 
		flag=1
		time#=timer()
	endif
    if flag=1 
		SetSpriteSize(castleSpr,GetSpriteWidth(castleSpr)+4,GetSpriteHeight(castleSpr)+4)
		SetSpriteSize(blackSpr,GetSpriteWidth(blackSpr)+8,GetSpriteHeight(blackSpr)+8)
		if time#+4&lt;timer()
			SetSpriteSize(castleSpr,GetimageWidth(castleImg),GetImageHeight(castleImg))
			SetSpriteSize(blackSpr,2,2):flag=0
		endif	
	endif	
    Print( ScreenFPS() )
    Sync()
loop
Posted: 13th Feb 2019 7:11
Wow - this looks interesting.

Cannot wait to test it out later on after work.

On Lemmings - I had the similar premise on shattering the follower in similar manner.

Cool
Posted: 13th Feb 2019 7:44
Wow - this looks interesting.

Ide also like to try as a memblock

where an image is though of as quarters
1,2
3,4
zone 1 pixels would move one to the left and one upward
zone 2 pixels would move one to the right and one upward
zone 3 pixels would move one to the left and one down
zone 4 pixels would move one to the right and one down

I think that could give a nice effect still not like it works in 3d as parts lol but might look good

then return the new image
replace old image with new one
maybe delete old image for code housekeeping

just will have to have a think about memblocks first as a slight incorrect placement will cause program crashes
Posted: 14th Feb 2019 22:03
Nice work fubarpk I try to press spacebar twice but couldn't get it repit
Posted: 17th Feb 2019 19:11
So just that we dont loose touch with this - may come in handy with lots of things

Object Mesh Building

+ Code Snippet
// Project: heights 
// Created: 2019-01-01
  
// show all errors
SetErrorMode(2)
  
#constant screenwidth=1024
#constant screenheight=768
#constant fullscreen=0
#constant screenrate=0
  
// set window properties
SetWindowTitle( "heights" )
SetWindowSize( screenwidth, screenheight, fullscreen )
SetWindowAllowResize( 1 ) // allow the user to resize the window
  
// set display properties
SetVirtualResolution( screenwidth, screenheight ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( screenrate, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
  
#constant sizex=20 // change this to extend the map
#constant sizez=20 // change this to exeend the map
global angx#, angy#,startx#,starty#
startx#=screenwidth/2
starty#=screenheight/2

size=5
 
type _map
    id
    x#
    height#
    z#
    colorred
    colorgreen
    colorblue
    texture
endtype
 
global map as _map[sizex,sizez]

global vertexnumber

land = CreateObjectBox(.01,.01,.01)
for x=1 to sizex
    for z=1 to sizez
        map[x,z].id = CreateObjectBox(9,9,9)
        map[x,z].x# = x * GetObjectSizeMaxX(map[x,z].id)*2 // Remove the * 2 to join the cubes together
        map[x,z].height#=random(0,0)
        map[x,z].z# = z * GetObjectSizeMaxZ(map[x,z].id)*2 // Remove the * 2 to join the cubes together
		map[x,z].colorgreen = random(150,200)
		
        SetObjectColor(map[x,z].id,0,map[x,z].colorgreen,0,255)
        SetObjectPosition(map[x,z].id,map[x,z].x#,0,map[x,z].z#)
        FixObjectToObject(map[x,z].id,land)
        
    next
next

RotateObjectLocalY(land,-30)
prepareheights()
 
camerax#=20
cameray#=30
cameraz#=0

 
// frameImg=LoadImage("\media\frame2.png")
//FrameSpr=createSprite(frameImg) 
collisioner=CreateObjectBox(10,10,10)
do
 
  //  SetSpriteDepth(frameSpr,100) //set the frame to behind all tiles to allow clicking to work

	unit_x#=Get3DVectorXFromScreen(getpointerx(),getpointery())
	unit_y#=Get3DVectorYFromScreen(getpointerx(),getpointery())
	unit_z#=Get3DVectorZFromScreen(getpointerx(),getpointery())	
	// calculate the start of the ray cast, which is the unit vector + the camera position
        start_x# = unit_x# + camerax#
        start_y# = unit_y# + cameray#
        start_z# = unit_z# - cameraz#

        // calculate the end of the vector, which is the unit vector multiplied by the length of the ray cast and then add the camera position to it
        end_x# = 800*unit_x# + camerax#
        end_y# = 800*unit_y# + cameray#
        end_z# = 800*unit_z# - cameraz#

        // determine which object has been hit
        object_hit = ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)

        // if an object has been hit then turn it red
        if object_hit &lt;&gt; 0

			x=getobjectx(object_hit)/9
			z=getobjectz(object_hit)/9
			
		else
        endif


	
    if GetRawKeyState(13)
		RotateObjectLocalY(land,.05)
	endif
    if GetRawMouseLeftPressed()
        inc map[x,z].height#,2
        SetObjectPosition(map[x,z].id,map[x,z].x#,map[x,z].height#,map[x,z].z#)
        changeverts(x,z,2)
		
    endif


    if GetRawMouseRightPressed()
        dec map[x,z].height#,2
        SetObjectPosition(map[x,z].id,map[x,z].x#,map[x,z].height#,map[x,z].z#)
        changeverts(x,z,-2)
		
    endif

    if GetRawKeyState(68) then inc camerax#,.1
    if GetRawKeyState(65) then dec camerax#,.1
    if GetRawKeyState(83) then inc cameray#,.1
    if GetRawKeyState(87) then dec cameray#,.1
     
         movecamera()

    SetCameraPosition(1,camerax#,cameray#,cameraz#)
    Print( ScreenFPS() )
    Sync()
loop

function movecamera()
    if GetRawKeyState(32)
    fDiffX# = (GetPointerX() - startx#)/4.0
    fDiffY# = (GetPointerY() - starty#)/4.0
    newX# = angx# + fDiffY#
    if ( newX# &gt; 89 ) then newX# = 89
    if ( newX# &lt; -89 ) then newX# = -89
    SetCameraRotation(1, newX#, angy# + fDiffX#, 0 )
    endif
endfunction
  
function prepareheights()
	for x=2 to sizex-1
		for z=2 to sizez-1
			changeverts(x,z,map[x,z].height#)
		next
	next
endfunction
  
function changeverts(x,z,slope#)
     
            CreateMemblockFromObjectMesh(2,map[x+1,z-1].id,1) // bottom right corner
            CreateMemblockFromObjectMesh(4,map[x+1,z+1].id,1) // top right corner
            CreateMemblockFromObjectMesh(5,map[x-1,z+1].id,1) // top left corner
            CreateMemblockFromObjectMesh(6,map[x-1,z-1].id,1) // bottom left corner
   
            CreateMemblockFromObjectMesh(3,map[x+1,z].id,1) // right edges
 
            CreateMemblockFromObjectMesh(7,map[x-1,z].id,1) // left cube edges
           CreateMemblockFromObjectMesh(8,map[x,z-1].id,1) // bottom cube edges
           CreateMemblockFromObjectMesh(9,map[x,z+1].id,1) // top cube edges
 
             
    for i=0 to 23
         
// bottom rightcorner
        if i=8 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
        if i=16 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
        if i=14 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
 
// top rightcorner
        if i=9 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
        if i=0 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
        if i=18 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
 
// top leftcorner
        if i=11 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
        if i=2 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
       if i=4 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
  
 
// tbottom leftcorner
        if i=10 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
        if i=6 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
        if i=12 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
 
 
// right cube
        if i=8 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=9 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=16 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=18 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=0 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=14 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
 
// left cube
        if i=10 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=11 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=4 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=6 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=2 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=12 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        
// bottom cube
        if i=8 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=10 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=6 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=12 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=14 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=16 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
 
// top cube
        if i=9 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=11 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=0 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=2 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=4 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=18 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
 
    next
     
    SetObjectMeshFromMemblock(map[x+1,z-1].id,1,2)   
    SetObjectMeshFromMemblock(map[x+1,z].id,1,3)   
    SetObjectMeshFromMemblock(map[x+1,z+1].id,1,4)   
    SetObjectMeshFromMemblock(map[x-1,z+1].id,1,5)   
    SetObjectMeshFromMemblock(map[x-1,z-1].id,1,6)   
    SetObjectMeshFromMemblock(map[x-1,z].id,1,7)   
    SetObjectMeshFromMemblock(map[x,z-1].id,1,8)   
    SetObjectMeshFromMemblock(map[x,z+1].id,1,9)   
 
 
 
    DeleteMemblock(2)
    DeleteMemblock(3)
    DeleteMemblock(4)
    DeleteMemblock(5)
    DeleteMemblock(6)
    DeleteMemblock(7)
    DeleteMemblock(8)
    DeleteMemblock(9)
  
  
endfunction


Left click block to raise
Right click block to lower

Space and mouse move changes camera
Posted: 17th Feb 2019 19:16
Thanks puzzler ive spent ages going through threads in the past
to find code that's buried deep in some other code in one of the pages
Object Mesh Building
Changed to the following this way it don't ever error and a few other things like crater creation etc
+ Code Snippet
// Project: heights 
// Created: 2019-01-01
   
// show all errors
SetErrorMode(2)
   
#constant screenwidth=1024
#constant screenheight=768
#constant fullscreen=0
#constant screenrate=0
   
// set window properties
SetWindowTitle( "heights" )
SetWindowSize( screenwidth, screenheight, fullscreen )
SetWindowAllowResize( 1 ) // allow the user to resize the window
   
// set display properties
SetVirtualResolution( screenwidth, screenheight ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( screenrate, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
Create3DPhysicsWorld()  
#constant sizex=21 // change this to extend the map
#constant sizez=21 // change this to exeend the map
global angx#, angy#,startx#,starty#
startx#=screenwidth/2
starty#=screenheight/2
 
size=5
 
type _map
    id
    x#
    height#
    z#
    colorred
    colorgreen
    colorblue
    texture
endtype
  
global map as _map[sizex,sizez]
 
global vertexnumber

//textimages as integer[10]
//for loops=0 to 10
//   textimages[loops]= createtexture(64,64,MakeColor(0,255,0),255)
//next
textimages as integer[10]
textimages[0]= createtexture(64,64,MakeColor(0,255,0),255)
textimages[1]= createtexture(64,64,MakeColor(255,255,255),255)

land = CreateObjectBox(.01,.01,.01)
colorgreen=150
for x=1 to sizex
    for z=1 to sizez
        map[x,z].id = CreateObjectBox(9,9,9)
        map[x,z].x# = x * GetObjectSizeMaxX(map[x,z].id)*2 // Remove the * 2 to join the cubes together
        map[x,z].height#=random(0,0)
        map[x,z].z# = z * GetObjectSizeMaxZ(map[x,z].id)*2 // Remove the * 2 to join the cubes together

        //map[x,z].colorgreen = random(150,200)
		//SetObjectImage(map[x,z].id,textimages[0],0)
		if colorgreen=150
			colorgreen=200
		else
			colorgreen=150
		endif
				
		map[x,z].colorgreen =colorGreen	
		SetObjectImage(map[x,z].id,textimages[0],0)
		
        Create3DPhysicsStaticBody(map[x,z].id)   
        SetObjectColor(map[x,z].id,0,map[x,z].colorgreen,0,255)
        SetObjectPosition(map[x,z].id,map[x,z].x#,0,map[x,z].z#)
        FixObjectToObject(map[x,z].id,land)
        		
    next
next
 
RotateObjectLocalY(land,-30)
prepareheights()
  
camerax#=20
cameray#=30
cameraz#=0
 
  
// frameImg=LoadImage("\media\frame2.png")
//FrameSpr=createSprite(frameImg) 
collisioner=CreateObjectBox(10,10,10)
do
  
  //  SetSpriteDepth(frameSpr,100) //set the frame to behind all tiles to allow clicking to work
 
    unit_x#=Get3DVectorXFromScreen(getpointerx(),getpointery())
    unit_y#=Get3DVectorYFromScreen(getpointerx(),getpointery())
    unit_z#=Get3DVectorZFromScreen(getpointerx(),getpointery()) 
    // calculate the start of the ray cast, which is the unit vector + the camera position
        start_x# = unit_x# + camerax#
        start_y# = unit_y# + cameray#
        start_z# = unit_z# - cameraz#
 
        // calculate the end of the vector, which is the unit vector multiplied by the length of the ray cast and then add the camera position to it
        end_x# = 800*unit_x# + camerax#
        end_y# = 800*unit_y# + cameray#
        end_z# = 800*unit_z# - cameraz#
 
        // determine which object has been hit
        object_hit = ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)
 
        // if an object has been hit then turn it red
        if object_hit &lt;&gt; 0
 
            x=getobjectx(object_hit)/9
            z=getobjectz(object_hit)/9
             
        else
        endif
 
 
     
    if GetRawKeyState(13)
        RotateObjectLocalY(land,.05)
    endif
    if GetRawMouseLeftState()
        flag=1
        if x&lt;2 or x&gt;sizex-1 then flag=0
        if z&lt;2 or z&gt;sizez-1 then flag=0
        if flag=1
            inc map[x,z].height#,.01
            SetObjectPosition(map[x,z].id,map[x,z].x#,map[x,z].height#,map[x,z].z#)
            changeverts(x,z,.01)
            Delete3DPhysicsBody(map[x,z].id) 
            Create3DPhysicsStaticBody(map[x,z].id)   
        endif
    endif
 
 
    if GetRawMouseRightState()
        flag=1
        if x&lt;2 or x&gt;sizex-1 then flag=0
        if z&lt;2 or z&gt;sizez-1 then flag=0
        if flag=1 and map[x,z].height#&gt;0
            dec map[x,z].height#,.01
            SetObjectPosition(map[x,z].id,map[x,z].x#,map[x,z].height#,map[x,z].z#)
            changeverts(x,z,-.01)
            Delete3DPhysicsBody(map[x,z].id) 
            Create3DPhysicsStaticBody(map[x,z].id)   
        endif
    endif
     
    if GetRawMouseMiddlePressed() 
        flag=1
        if x&lt;2 or x&gt;sizex-1 then flag=0
        if z&lt;2 or z&gt;sizez-1 then flag=0
        if flag=1 
			//if map[x,z].height#&gt;0
				dec map[x,z].height#,10
				SetObjectPosition(map[x,z].id,map[x,z].x#,map[x,z].height#,map[x,z].z#)
				changeverts(x,z,-10.01)
				Delete3DPhysicsBody(map[x,z].id) 
				Create3DPhysicsStaticBody(map[x,z].id)
            //endif   
			//SetObjectColor(map[x,z].id,GetObjectColorRed(map[x,z].id)-50,GetObjectColorGreen(map[x,z].id)-50,GetObjectColorBlue(map[x,z].id)-50,255)  
			//SetObjectColor(map[x+1,z+1].id,GetObjectColorRed(map[x+1,z+1].id)-50,GetObjectColorGreen(map[x+1,z+1].id)-50,GetObjectColorBlue(map[x+1,z+1].id)-50,255)  
			//SetObjectColor(map[x-1,z+1].id,GetObjectColorRed(map[x-1,z+1].id)-50,GetObjectColorGreen(map[x-1,z+1].id)-50,GetObjectColorBlue(map[x-1,z+1].id)-50,255)  
			//SetObjectColor(map[x-1,z-1].id,GetObjectColorRed(map[x-1,z-1].id)-50,GetObjectColorGreen(map[x-1,z-1].id)-50,GetObjectColorBlue(map[x-1,z-1].id)-50,255)  
			//SetObjectColor(map[x+1,z].id,GetObjectColorRed(map[x+1,z].id)-50,GetObjectColorGreen(map[x+1,z].id)-50,GetObjectColorBlue(map[x+1,z].id)-50,255)  
			//SetObjectColor(map[x-1,z].id,GetObjectColorRed(map[x-1,z].id)-50,GetObjectColorGreen(map[x-1,z].id)-50,GetObjectColorBlue(map[x-1,z].id)-50,255)  
			//SetObjectColor(map[x,z+1].id,GetObjectColorRed(map[x,z+1].id)-50,GetObjectColorGreen(map[x,z+1].id)-50,GetObjectColorBlue(map[x,z+1].id)-50,255)  
			//SetObjectColor(map[x,z-1].id,GetObjectColorRed(map[x,z-1].id)-50,GetObjectColorGreen(map[x,z-1].id)-50,GetObjectColorBlue(map[x,z-1].id)-50,255)  
			SetObjectColor(map[x,z].id,100,100,100,255):SetObjectImage(map[x,z].id,textImages[1],0)  
			SetObjectColor(map[x+1,z+1].id,100,100,100,255):SetObjectImage(map[x+1,z+1].id,textImages[1],0) 
			SetObjectColor(map[x-1,z+1].id,100,100,100,255):SetObjectImage(map[x-1,z+1].id,textImages[1],0) 
			SetObjectColor(map[x-1,z-1].id,100,100,100,255):SetObjectImage(map[x-1,z-1].id,textImages[1],0) 
			SetObjectColor(map[x+1,z].id,100,100,100,255):SetObjectImage(map[x+1,z].id,textImages[1],0) 
			SetObjectColor(map[x-1,z].id,100,100,100,255):SetObjectImage(map[x-1,z].id,textImages[1],0) 
			SetObjectColor(map[x,z+1].id,100,100,100,255):SetObjectImage(map[x,z+1].id,textImages[1],0) 
			SetObjectColor(map[x,z-1].id,100,100,100,255):SetObjectImage(map[x,z-1].id,textImages[1],0) 
			
		endif
        
    endif  
 
    if GetRawKeyState(68) then inc camerax#,.1
    if GetRawKeyState(65) then dec camerax#,.1
    if GetRawKeyState(83) then inc cameray#,.1
    if GetRawKeyState(87) then dec cameray#,.1
      
         movecamera()
 
    SetCameraPosition(1,camerax#,cameray#,cameraz#)
    Print( ScreenFPS() )
    Sync()
loop
 
function movecamera()
    if GetRawKeyState(32)
    fDiffX# = (GetPointerX() - startx#)/4.0
    fDiffY# = (GetPointerY() - starty#)/4.0
    newX# = angx# + fDiffY#
    if ( newX# &gt; 89 ) then newX# = 89
    if ( newX# &lt; -89 ) then newX# = -89
    SetCameraRotation(1, newX#, angy# + fDiffX#, 0 )
    endif
endfunction
   
function prepareheights()
    for x=2 to sizex-1
        for z=2 to sizez-1
            changeverts(x,z,map[x,z].height#)
        next
    next
endfunction
   
function changeverts(x,z,slope#)
      
            CreateMemblockFromObjectMesh(2,map[x+1,z-1].id,1) // bottom right corner
            CreateMemblockFromObjectMesh(4,map[x+1,z+1].id,1) // top right corner
            CreateMemblockFromObjectMesh(5,map[x-1,z+1].id,1) // top left corner
            CreateMemblockFromObjectMesh(6,map[x-1,z-1].id,1) // bottom left corner
    
            CreateMemblockFromObjectMesh(3,map[x+1,z].id,1) // right edges
  
            CreateMemblockFromObjectMesh(7,map[x-1,z].id,1) // left cube edges
           CreateMemblockFromObjectMesh(8,map[x,z-1].id,1) // bottom cube edges
           CreateMemblockFromObjectMesh(9,map[x,z+1].id,1) // top cube edges
  
              
    for i=0 to 23
          
// bottom rightcorner
        if i=8 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
        if i=16 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
        if i=14 then SetMeshMemblockVertexPosition(2,i,GetMeshMemblockVertexX(2,i),GetMeshMemblockVertexY(2,i)+slope#,GetMeshMemblockVertexZ(2,i))
  
// top rightcorner
        if i=9 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
        if i=0 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
        if i=18 then SetMeshMemblockVertexPosition(4,i,GetMeshMemblockVertexX(4,i),GetMeshMemblockVertexY(4,i)+slope#,GetMeshMemblockVertexZ(4,i))
  
// top leftcorner
        if i=11 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
        if i=2 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
       if i=4 then SetMeshMemblockVertexPosition(5,i,GetMeshMemblockVertexX(5,i),GetMeshMemblockVertexY(5,i)+slope#,GetMeshMemblockVertexZ(5,i))
   
  
// tbottom leftcorner
        if i=10 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
        if i=6 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
        if i=12 then SetMeshMemblockVertexPosition(6,i,GetMeshMemblockVertexX(6,i),GetMeshMemblockVertexY(6,i)+slope#,GetMeshMemblockVertexZ(6,i))
  
  
// right cube
        if i=8 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=9 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=16 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=18 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=0 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
        if i=14 then SetMeshMemblockVertexPosition(3,i,GetMeshMemblockVertexX(3,i),GetMeshMemblockVertexY(3,i)+slope#,GetMeshMemblockVertexZ(3,i))
  
// left cube
        if i=10 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=11 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=4 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=6 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=2 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
        if i=12 then SetMeshMemblockVertexPosition(7,i,GetMeshMemblockVertexX(7,i),GetMeshMemblockVertexY(7,i)+slope#,GetMeshMemblockVertexZ(7,i))
         
// bottom cube
        if i=8 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=10 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=6 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=12 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=14 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
        if i=16 then SetMeshMemblockVertexPosition(8,i,GetMeshMemblockVertexX(8,i),GetMeshMemblockVertexY(8,i)+slope#,GetMeshMemblockVertexZ(8,i))
  
// top cube
        if i=9 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=11 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=0 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=2 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=4 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
        if i=18 then SetMeshMemblockVertexPosition(9,i,GetMeshMemblockVertexX(9,i),GetMeshMemblockVertexY(9,i)+slope#,GetMeshMemblockVertexZ(9,i))
  
    next
      
    SetObjectMeshFromMemblock(map[x+1,z-1].id,1,2)   
    SetObjectMeshFromMemblock(map[x+1,z].id,1,3)   
    SetObjectMeshFromMemblock(map[x+1,z+1].id,1,4)   
    SetObjectMeshFromMemblock(map[x-1,z+1].id,1,5)   
    SetObjectMeshFromMemblock(map[x-1,z-1].id,1,6)   
    SetObjectMeshFromMemblock(map[x-1,z].id,1,7)   
    SetObjectMeshFromMemblock(map[x,z-1].id,1,8)   
    SetObjectMeshFromMemblock(map[x,z+1].id,1,9)   
  
  
  
  
  
  
    DeleteMemblock(2)
    DeleteMemblock(3)
    DeleteMemblock(4)
    DeleteMemblock(5)
    DeleteMemblock(6)
    DeleteMemblock(7)
    DeleteMemblock(8)
    DeleteMemblock(9)
   
   
endfunction

// Function to create a texture
//
// Inputs - Sizex - size of the texture to create - width
//          Sizey - size of the texture to create - height
//          Color - is the main color of the image
//          Denisity - is a the depth of the texture - the lower the value, the more detail. higher value = no detail
// 
// Returns the image for the resulting texture
//
// EG. CreateTexture ( 100, 100,  makecolor(0,0,255), 100)
//          This could create a DEEP water effect texture?
  
function createtexture(sizex# as float, sizey# as float, color, density as integer)
  
      
    swap()
    drawbox(0,0,sizex#, sizey#, color, color,color,color, 1)
    render()
    img = getimage(0,0,sizex#, sizey#)
      
    memblockid = CreateMemblockFromImage (img)
    imgwidth = GetMemblockInt(memblockid, 0)
    imgheight = GetMemblockInt(memblockid, 4)
      
      
        size=GetMemblockSize(memblockid)
  
        for offset=12 to size-4 step 4
        
            r=GetMemblockByte(memblockid, offset)
            g=GetMemblockByte(memblockid, offset+1)
            b=GetMemblockByte(memblockid, offset+2)
            a=GetMemblockByte(memblockid, offset+3)
              
          
            strength=random(1,density)
  
            SetMemblockByte (memblockid, offset, r-strength)
            SetMemblockByte (memblockid, offset+1, g-strength)
            SetMemblockByte (memblockid, offset+2, b-strength )
            SetMemblockByte (memblockid, offset+3, a-strength)
               
          
    next
      
    deleteimage (img)
      
    img = CreateImageFromMemblock(memblockid)
    DeleteMemblock(memblockid)
  
  
endfunction img
Posted: 5th Apr 2019 1:00
2D Clouds Sprite Shader
+ Code Snippet
#constant width = 1024
#constant height= 768

SetWindowSize( width, height, 0 )
SetVirtualResolution( width, height )
   
createShader()
CreateSprite(1,0)
SetSpriteSize(1,width,height)
cloudsShader=LoadSpriteShader("clouds.ps")
SetSpriteShader( 1,cloudsShader )


SetShaderConstantByName(cloudsShader,"resolution",width,height,0,0) 
SetShaderConstantByName(cloudsShader,"colorA",0.23, 0.4, 0.6,0) //the blue sky colour (values between 0 an 1)
SetShaderConstantByName(cloudsShader,"colorB",0.8, 0.8, 0.8,0) //the clouds colour

do
    time#=Timer()
    SetShaderConstantByName(cloudsShader,"time",time#,0,0,0) 
    print(ScreenFPS())
    sync()  
 
loop
 
function createTexture ()
    r=random(50,255): g=random(50,255):b=random(50,255)
    DrawBox(0,0,32,32,MakeColor(r,g,b),MakeColor(r,g,b),MakeColor(r,g,b),MakeColor(r,g,b),1)
    render()
    img=GetImage(0,0,32,32)    
endfunction img 
  
function createShader()
file = OpenToWrite("clouds.vs")
WriteLine(file,"attribute highp vec3 position;")
WriteLine(file,"attribute mediump vec3 normal;")
WriteLine(file,"attribute mediump vec2 uv;")
WriteLine(file,"varying highp vec3 posVarying;")
WriteLine(file,"varying mediump vec3 normalVarying;")
WriteLine(file,"varying mediump vec2 uvVarying;")
WriteLine(file,"varying mediump vec3 lightVarying;")
WriteLine(file,"uniform highp mat3 agk_WorldNormal;")
WriteLine(file,"uniform highp mat4 agk_World;")
WriteLine(file,"uniform highp mat4 agk_ViewProj;")
WriteLine(file,"uniform mediump vec4 uvBounds0;")
WriteLine(file,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(file,"void main()")
WriteLine(file,"{") 
WriteLine(file,"    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(file,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(file,"    gl_Position = agk_ViewProj * pos;")
WriteLine(file,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(file,"    posVarying = pos.xyz;")
WriteLine(file,"    normalVarying = norm;")
WriteLine(file,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(file,"}") 
CloseFile(file)	
	
	
 
file = OpenToWrite("clouds.ps")
WriteLine(file,"precision highp float;")
WriteLine(file,"#define OCTAVES  8.0")

//needed for 3D
WriteLine(file,"uniform sampler2D texture0;")
WriteLine(file,"varying mediump vec2 uvVarying;")

WriteLine(file,"uniform float time;")
WriteLine(file,"uniform vec3 colorA;")
WriteLine(file,"uniform vec3 colorB;")
WriteLine(file,"uniform vec2 resolution;")
WriteLine(file,"float rand2(vec2 co){")
WriteLine(file,"   return fract(cos(dot(co.xy ,vec2(12.9898,78.233))) * 4.5453);")
WriteLine(file,"}")
WriteLine(file,"float valueNoiseSimple(vec2 vl) {")
WriteLine(file,"   float minStep = 1.0 ;")
WriteLine(file,"   vec2 grid = floor(vl);")
WriteLine(file,"   vec2 gridPnt1 = grid;")
WriteLine(file,"   vec2 gridPnt2 = vec2(grid.x, grid.y + minStep);")
WriteLine(file,"   vec2 gridPnt3 = vec2(grid.x + minStep, grid.y);")
WriteLine(file,"   vec2 gridPnt4 = vec2(gridPnt3.x, gridPnt2.y);")
WriteLine(file,"    float s = rand2(gridPnt1);")
WriteLine(file,"    float t = rand2(gridPnt3);")
WriteLine(file,"    float u = rand2(gridPnt2);")
WriteLine(file,"    float v = rand2(gridPnt4);")
WriteLine(file,"    float x1 = smoothstep(0., 1., fract(vl.x));")
WriteLine(file,"    float interpX1 = mix(s, t, x1);")
WriteLine(file,"    float interpX2 = mix(u, v, x1);")
WriteLine(file,"    float y = smoothstep(0., 1., fract(vl.y));")
WriteLine(file,"    float interpY = mix(interpX1, interpX2, y);")
WriteLine(file,"    return interpY;")
WriteLine(file,"}")
WriteLine(file,"float fractalNoise(vec2 vl) {")
WriteLine(file,"    float persistance = 2.0;")
WriteLine(file,"    float amplitude = 0.5;")
WriteLine(file,"    float rez = 0.0;")
WriteLine(file,"    vec2 p = vl;")
WriteLine(file,"    for (float i = 0.0; i &lt; OCTAVES; i++) {")
WriteLine(file,"        rez += amplitude * valueNoiseSimple(p);")
WriteLine(file,"        amplitude /= persistance;")
WriteLine(file,"        p *= persistance;")
WriteLine(file,"    }")
WriteLine(file,"    return rez;")
WriteLine(file,"}")
WriteLine(file,"float complexFBM(vec2 p) {")
WriteLine(file,"    const float NUM_FREQS = 32.0;")
WriteLine(file,"    float slow = time / 16.;")
WriteLine(file,"    float fast = time / 2.;")
WriteLine(file,"    vec2 offset1 = vec2(slow  , 0.);")
WriteLine(file,"    vec2 offset2 = vec2(sin(fast)* 0.1, 0.);")
WriteLine(file,"    return")
WriteLine(file,"        (1. + 0.35) *")
WriteLine(file,"        fractalNoise( p + offset1 + fractalNoise(")
WriteLine(file,"            p + fractalNoise(")
WriteLine(file,"                p + 2. * fractalNoise(p - offset2)")
WriteLine(file,"            )")
WriteLine(file,"        )")
WriteLine(file,"        );")
WriteLine(file,"}")
WriteLine(file,"void main() {")
WriteLine(file,"    vec2 uv = gl_FragCoord.xy / resolution.xy;")
WriteLine(file,"    uv.x *= resolution.x / resolution.y;")
WriteLine(file,"    vec3 rez = mix(colorA, colorB, complexFBM(uv) * 1.5 + uv.y * 0.8 - sin(time * 0.1) * 0.5 - 0.7);")
WriteLine(file,"	gl_FragColor = vec4(rez, 1.0);")

WriteLine(file,"}")
CloseFile(file)
endfunction  


3D Clouds Shader Same as above but 3D version
+ Code Snippet
#constant width = 1024
#constant height= 768

SetWindowSize( width, height, 0 )
SetVirtualResolution( width, height )
   
createShader()
backObj=CreateObjectPlane(45,40)
SetObjectImage(backObj,createTexture(),0)
cloudsShader=LoadShader("clouds.vs", "clouds.ps")
SetObjectShader(backObj,cloudsShader)

SetShaderConstantByName(cloudsShader,"resolution",width,height,0,0) 
SetShaderConstantByName(cloudsShader,"colorA",0.23, 0.4, 0.6,0) //the blue sky colour (values between 0 an 1)
SetShaderConstantByName(cloudsShader,"colorB",0.8, 0.8, 0.8,0) //the clouds colour

do
    time#=Timer()
    SetShaderConstantByName(cloudsShader,"time",time#,0,0,0) 
    print(ScreenFPS())
    sync()  
 
loop
 
function createTexture ()
    r=random(50,255): g=random(50,255):b=random(50,255)
    DrawBox(0,0,32,32,MakeColor(r,g,b),MakeColor(r,g,b),MakeColor(r,g,b),MakeColor(r,g,b),1)
    render()
    img=GetImage(0,0,32,32)    
endfunction img 
  
function createShader()
file = OpenToWrite("clouds.vs")
WriteLine(file,"attribute highp vec3 position;")
WriteLine(file,"attribute mediump vec3 normal;")
WriteLine(file,"attribute mediump vec2 uv;")
WriteLine(file,"varying highp vec3 posVarying;")
WriteLine(file,"varying mediump vec3 normalVarying;")
WriteLine(file,"varying mediump vec2 uvVarying;")
WriteLine(file,"varying mediump vec3 lightVarying;")
WriteLine(file,"uniform highp mat3 agk_WorldNormal;")
WriteLine(file,"uniform highp mat4 agk_World;")
WriteLine(file,"uniform highp mat4 agk_ViewProj;")
WriteLine(file,"uniform mediump vec4 uvBounds0;")
WriteLine(file,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(file,"void main()")
WriteLine(file,"{") 
WriteLine(file,"    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(file,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(file,"    gl_Position = agk_ViewProj * pos;")
WriteLine(file,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(file,"    posVarying = pos.xyz;")
WriteLine(file,"    normalVarying = norm;")
WriteLine(file,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(file,"}") 
CloseFile(file)	
	 
file = OpenToWrite("clouds.ps")
WriteLine(file,"precision highp float;")
WriteLine(file,"#define OCTAVES  8.0")
WriteLine(file,"uniform sampler2D texture0;")
WriteLine(file,"varying mediump vec2 uvVarying;")
WriteLine(file,"uniform float time;")
WriteLine(file,"uniform vec3 colorA;")
WriteLine(file,"uniform vec3 colorB;")
WriteLine(file,"uniform vec2 resolution;")
WriteLine(file,"float rand2(vec2 co){")
WriteLine(file,"   return fract(cos(dot(co.xy ,vec2(12.9898,78.233))) * 4.5453);")
WriteLine(file,"}")
WriteLine(file,"float valueNoiseSimple(vec2 vl) {")
WriteLine(file,"   float minStep = 1.0 ;")
WriteLine(file,"   vec2 grid = floor(vl);")
WriteLine(file,"   vec2 gridPnt1 = grid;")
WriteLine(file,"   vec2 gridPnt2 = vec2(grid.x, grid.y + minStep);")
WriteLine(file,"   vec2 gridPnt3 = vec2(grid.x + minStep, grid.y);")
WriteLine(file,"   vec2 gridPnt4 = vec2(gridPnt3.x, gridPnt2.y);")
WriteLine(file,"    float s = rand2(gridPnt1);")
WriteLine(file,"    float t = rand2(gridPnt3);")
WriteLine(file,"    float u = rand2(gridPnt2);")
WriteLine(file,"    float v = rand2(gridPnt4);")
WriteLine(file,"    float x1 = smoothstep(0., 1., fract(vl.x));")
WriteLine(file,"    float interpX1 = mix(s, t, x1);")
WriteLine(file,"    float interpX2 = mix(u, v, x1);")
WriteLine(file,"    float y = smoothstep(0., 1., fract(vl.y));")
WriteLine(file,"    float interpY = mix(interpX1, interpX2, y);")
WriteLine(file,"    return interpY;")
WriteLine(file,"}")
WriteLine(file,"float fractalNoise(vec2 vl) {")
WriteLine(file,"    float persistance = 2.0;")
WriteLine(file,"    float amplitude = 0.5;")
WriteLine(file,"    float rez = 0.0;")
WriteLine(file,"    vec2 p = vl;")
WriteLine(file,"    for (float i = 0.0; i &lt; OCTAVES; i++) {")
WriteLine(file,"        rez += amplitude * valueNoiseSimple(p);")
WriteLine(file,"        amplitude /= persistance;")
WriteLine(file,"        p *= persistance;")
WriteLine(file,"    }")
WriteLine(file,"    return rez;")
WriteLine(file,"}")
WriteLine(file,"float complexFBM(vec2 p) {")
WriteLine(file,"    const float NUM_FREQS = 32.0;")
WriteLine(file,"    float slow = time / 16.;")
WriteLine(file,"    float fast = time / 2.;")
WriteLine(file,"    vec2 offset1 = vec2(slow  , 0.);")
WriteLine(file,"    vec2 offset2 = vec2(sin(fast)* 0.1, 0.);")
WriteLine(file,"    return")
WriteLine(file,"        (1. + 0.35) *")
WriteLine(file,"        fractalNoise( p + offset1 + fractalNoise(")
WriteLine(file,"            p + fractalNoise(")
WriteLine(file,"                p + 2. * fractalNoise(p - offset2)")
WriteLine(file,"            )")
WriteLine(file,"        )")
WriteLine(file,"        );")
WriteLine(file,"}")
WriteLine(file,"void main() {")
WriteLine(file,"    vec2 uv = gl_FragCoord.xy / resolution.xy;")
WriteLine(file,"    uv.x *= resolution.x / resolution.y;")
WriteLine(file,"    vec3 rez = mix(colorA, colorB, complexFBM(uv) * 1.5 + uv.y * 0.8 - sin(time * 0.1) * 0.5 - 0.7);")
WriteLine(file,"vec3 color = texture2D(texture0, uvVarying).rgb;")
WriteLine(file,"color.r=rez.r;")
WriteLine(file,"color.g=rez.g;")
WriteLine(file,"color.b=rez.g;")
WriteLine(file,"color = clamp(color,0.0,1.0);") //restricts color range
WriteLine(file,"gl_FragColor = vec4(color,1.0);")

WriteLine(file,"}")
CloseFile(file)
endfunction 
Posted: 24th May 2019 0:12
factorial function
+ Code Snippet
function fact(n as integer) 
    /* n=0 indicates a terminating condition */    
if n &lt;= 0 
	exitfunction (1)
else 
  exitfunction (n * fact(n - 1))
endif
endfunction 0
Posted: 24th May 2019 8:11
Hi! didn't know where to post my question, but since its 3d related and need a little snippet i thought about posting here.
Does anyone know how to get multiplayer with game guru loader? Any orientation will be greatly appreciated.
Posted: 24th May 2019 9:11
@shiku316 you would do best to start your own thread as more people would see it
and your more likely to find a solution to your problem
Posted: 2nd Jul 2019 1:02
not sure how useful people will find this
but if you want to pixelate the texture of a 3D object using a shader
+ Code Snippet
SetErrorMode(2)

// set window properties
SetWindowTitle( "Pixelate" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

createShaderFile()
imgId=createRandomBgImage()
//CreateSprite(1,imgId)
CreateObjectBox(1,5,5,5)
SetObjectImage(1,imgId,0)
//LoadSpriteShader(2, "pixelate.ps")
//SetSpriteShader( 1,2 )
LoadShader(2,"pixelate.vs","pixelate.ps")
SetObjectShader(1,2)
do
	if GetRawKeyPressed(32) then SetCameraPosition(1,GetCameraX(1),GetCameraY(1),GetCameraZ(1)+.5)
    SetShaderConstantByName(2,"pixels",15,10,0,0) //the bigger the numbers the more pixels
    sync()   
loop

function createShaderFile()
fw = OpenToWrite("pixelate.vs")
WriteLine(fw,"attribute highp vec3 position;")
WriteLine(fw,"attribute mediump vec3 normal;")
WriteLine(fw,"attribute mediump vec2 uv;")
WriteLine(fw,"varying highp vec3 posVarying;")
WriteLine(fw,"varying mediump vec3 normalVarying;")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"varying mediump vec3 lightVarying;")
WriteLine(fw,"uniform highp mat3 agk_WorldNormal;")
WriteLine(fw,"uniform highp mat4 agk_World;")
WriteLine(fw,"uniform highp mat4 agk_ViewProj;")

WriteLine(fw,"uniform vec2 pixels; ")
WriteLine(fw,"uniform sampler2D texture0; // input channel")

WriteLine(fw,"uniform mediump vec4 uvBounds0;")
WriteLine(fw,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(fw,"void main()")
WriteLine(fw,"{") 
WriteLine(fw,"    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(fw,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(fw,"    gl_Position = agk_ViewProj * pos;")
WriteLine(fw,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(fw,"    posVarying = pos.xyz;")
WriteLine(fw,"    normalVarying = norm;")
WriteLine(fw,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(fw,"}") 
CloseFile(fw)

fw=OpenToWrite("pixelate.ps")
WriteLine(fw,"#ifdef GL_ES")
WriteLine(fw,"precision mediump float;")
WriteLine(fw,"precision mediump int;")
WriteLine(fw,"#endif")
WriteLine(fw,"#define PROCESSING_TEXTURE_SHADER")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"uniform sampler2D texture0;")
WriteLine(fw,"uniform vec2 pixels;")
WriteLine(fw,"void main(void)")
WriteLine(fw,"{")
WriteLine(fw,"  vec2 p = uvVarying;")
WriteLine(fw,"	p.x -= mod(p.x, 1.0 / pixels.x);")
WriteLine(fw,"	p.y -= mod(p.y, 1.0 / pixels.y);")
WriteLine(fw,"	vec3 col = texture2D(texture0, p).rgb;")
WriteLine(fw,"	gl_FragColor = vec4(col, 1.0);")
WriteLine(fw,"}")
CloseFile(fw)
endfunction

function createRandomBgImage()
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    For num = 1 to 500
		DrawEllipse(Random(1,1023),Random(1,787),random(10,30),random(10,30),makecolor(random(1,255),random(1,255),random(1,255)),makecolor(random(1,255),random(1,255),random(1,255)),1)
    next num
    swap()
    img = getimage(0,0,1024,768)
    //SetImageTransparentColor(img,0,0,0)
endfunction img
Posted: 2nd Jul 2019 10:05
@ fubarpk This will come very handy for my retro game . Thanks for sharing
Posted: 2nd Jul 2019 15:15
thanks glad you like it Chafari
I was thinking it could be used to bring things in and out of resolution like (use arrow keys)
+ Code Snippet
SetErrorMode(2)

// set window properties
SetWindowTitle( "Pixelate" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

createShaderFile()
imgId=createRandomBgImage()
//CreateSprite(1,imgId)
CreateObjectBox(1,5,5,5)
SetObjectImage(1,imgId,0)
//LoadSpriteShader(2, "pixelate.ps")
//SetSpriteShader( 1,2 )
LoadShader(2,"pixelate.vs","pixelate.ps")
SetObjectShader(1,2)
x=10.0:y=10.0
do
	if GetRawKeyState(38) 
		if x&lt;1024 then x=x+1:if y &lt; 768 then y=y+1
    endif
    if GetRawKeyState(40) 
		if x&gt;2 then x=x-1:if y&gt;2 then y=y-1
    endif
    SetShaderConstantByName(2,"pixels",x,y,0,0) //the bigger the numbers the more pixels
    print("x "+str(x))
    print("y "+str(y))
    print (ScreenFPS())
    sync()   
loop

function createShaderFile()
fw = OpenToWrite("pixelate.vs")
WriteLine(fw,"attribute highp vec3 position;")
WriteLine(fw,"attribute mediump vec3 normal;")
WriteLine(fw,"attribute mediump vec2 uv;")
WriteLine(fw,"varying highp vec3 posVarying;")
WriteLine(fw,"varying mediump vec3 normalVarying;")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"varying mediump vec3 lightVarying;")
WriteLine(fw,"uniform highp mat3 agk_WorldNormal;")
WriteLine(fw,"uniform highp mat4 agk_World;")
WriteLine(fw,"uniform highp mat4 agk_ViewProj;")

WriteLine(fw,"uniform vec2 pixels; ")
WriteLine(fw,"uniform sampler2D texture0; // input channel")

WriteLine(fw,"uniform mediump vec4 uvBounds0;")
WriteLine(fw,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(fw,"void main()")
WriteLine(fw,"{") 
WriteLine(fw,"    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(fw,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(fw,"    gl_Position = agk_ViewProj * pos;")
WriteLine(fw,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(fw,"    posVarying = pos.xyz;")
WriteLine(fw,"    normalVarying = norm;")
WriteLine(fw,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(fw,"}") 
CloseFile(fw)

fw=OpenToWrite("pixelate.ps")
WriteLine(fw,"#ifdef GL_ES")
WriteLine(fw,"precision mediump float;")
WriteLine(fw,"precision mediump int;")
WriteLine(fw,"#endif")
WriteLine(fw,"#define PROCESSING_TEXTURE_SHADER")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"uniform sampler2D texture0;")
WriteLine(fw,"uniform vec2 pixels;")
WriteLine(fw,"void main(void)")
WriteLine(fw,"{")
WriteLine(fw,"  vec2 p = uvVarying;")
WriteLine(fw,"	p.x -= mod(p.x, 1.0 / pixels.x);")
WriteLine(fw,"	p.y -= mod(p.y, 1.0 / pixels.y);")
WriteLine(fw,"	vec3 col = texture2D(texture0, p).rgb;")
WriteLine(fw,"	gl_FragColor = vec4(col, 1.0);")
WriteLine(fw,"}")
CloseFile(fw)
endfunction

function createRandomBgImage()
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    For num = 1 to 500
		DrawEllipse(Random(1,1023),Random(1,787),random(10,30),random(10,30),makecolor(random(1,255),random(1,255),random(1,255)),makecolor(random(1,255),random(1,255),random(1,255)),1)
    next num
    swap()
    img = getimage(0,0,1024,768)
    //SetImageTransparentColor(img,0,0,0)
endfunction img


or to imitate digital tv reception problems
Posted: 2nd Jul 2019 16:32
Yeah !! You are a genius !! this could be useful for camera depth making object more blured in the distance ...I will make some test later on .
Posted: 2nd Jul 2019 17:12
Thanks
Ive been playing with the scanline shader

+ Code Snippet
SetErrorMode(2)

// set window properties
SetWindowTitle( "3D scanlines" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

createShaderFile()
imgId=createRandomBgImage()
//imgId=LoadImage("zombie.png")
//CreateSprite(1,imgId)
CreateObjectBox(1,5,5,5)
//loadObject(1,"zombie.3ds")
SetObjectPosition(1,getObjectX(1),getObjectY(1)-5,getObjectZ(1))
SetObjectImage(1,imgId,0)
//LoadSpriteShader(2, "pixelate.ps")
//SetSpriteShader( 1,2 )
LoadShader(2,"scanlines.vs","scanlines.ps")
SetObjectShader(1,2)
SetShaderConstantByName(2,"iResolution",1024,768,0,0 )
x=10.0:y=10.0
do
	if GetRawKeyState(38) 
		if x&lt;1024 then x=x+1:if y &lt; 768 then y=y+1
    endif
    if GetRawKeyState(40) 
		if x&gt;2 then x=x-1:if y&gt;2 then y=y-1
    endif
    rotateObjectLocalY(1,1)
    //SetShaderConstantByName(2,"pixels",x,y,0,0) //the bigger the numbers the more pixels
    SetShaderConstantByName(2,"time",Timer(),0,0,0 )
    print("x "+str(x))
    print("y "+str(y))
    print (ScreenFPS())
    sync()   
loop

function createShaderFile()
     
    fw = OpenToWrite("scanlines.vs")
    WriteLine(fw,"attribute highp vec3 position;")
    WriteLine(fw,"attribute mediump vec3 normal;")
    WriteLine(fw,"varying highp vec3 posVarying;")
    WriteLine(fw,"varying mediump vec3 normalVarying;")
    WriteLine(fw,"varying mediump vec3 lightVarying;")
    WriteLine(fw,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
    WriteLine(fw,"uniform highp mat3 agk_WorldNormal;")
    WriteLine(fw,"uniform highp mat4 agk_World;")
    WriteLine(fw,"uniform highp mat4 agk_ViewProj;")
    WriteLine(fw,"attribute highp vec2 uv;")
    WriteLine(fw,"varying highp vec2 uvVarying;")
    WriteLine(fw,"uniform highp vec4 uvBounds0;")
    WriteLine(fw,"uniform sampler2D texture0; // input channel")  
    WriteLine(fw,"void main()")
    WriteLine(fw,"{ ")
    WriteLine(fw,"uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
    WriteLine(fw,"highp vec4 pos = agk_World * vec4(position,1.0);")
    WriteLine(fw,"mediump vec3 norm = normalize(agk_WorldNormal * normal);")
    WriteLine(fw,"gl_Position = agk_ViewProj * pos;")
    WriteLine(fw,"posVarying = pos.xyz;")
    WriteLine(fw,"normalVarying = norm;")
    WriteLine(fw,"lightVarying = GetVSLighting( norm, posVarying );")
    WriteLine(fw,"}")
    CloseFile(fw)   
 
	fw=OpenToWrite("scanlines.ps")
	WriteLine(fw,"#ifdef GL_ES")
	WriteLine(fw,"precision mediump float;")
	WriteLine(fw,"#endif")
	WriteLine(fw,"varying mediump vec2 uvVarying;")
	WriteLine(fw,"uniform vec2 iResolution;")
	WriteLine(fw,"uniform float time;")
	WriteLine(fw,"uniform sampler2D texture0; // input channel")
	WriteLine(fw,"#define num 60.0")
	WriteLine(fw,"float random(vec2 p){")
	WriteLine(fw,"  return fract(sin(dot(p, vec2(12.9898,78.233))) * 43758.5453+time*4.0);  ")
	WriteLine(fw,"}")
	WriteLine(fw,"void main() {")
	WriteLine(fw,"      vec2 p = ( gl_FragCoord.xy / (iResolution.xy) );")
	WriteLine(fw,"  //- vec2(0.5, 0.5);")
	WriteLine(fw,"  //vec2 p = (gl_FragCoord.xy * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y) - vec2(.5 , .5);")
	WriteLine(fw,"      float top, bottom, linewidth;")
	WriteLine(fw,"  float offSet = 0.5;")
	WriteLine(fw,"  float span = 0.01;")
	WriteLine(fw,"  linewidth = 0.01;")
	WriteLine(fw,"      top = fract(time);")
	WriteLine(fw,"  bottom = fract(time) + linewidth;")
	WriteLine(fw,"  vec4 border = vec4(0.0, 0.0, 0.0, 1.0);")
	WriteLine(fw,"  for(float i = 1.0; i &lt; num; i++){")
	WriteLine(fw,"      top += i * span; ")
	WriteLine(fw,"      top = fract(top);")
	WriteLine(fw,"      bottom += i *span;")
	WriteLine(fw,"      bottom = fract(bottom);")
	WriteLine(fw,"      if(p.y &gt; top &amp;&amp; p.y &lt; bottom){")
	WriteLine(fw,"      border = vec4(abs(1.0 * sin(time)), 0.0, 0.0, 1.0);")
	WriteLine(fw,"      }")
	WriteLine(fw,"  }")
	WriteLine(fw,"  float c = random(p);")
	WriteLine(fw,"  vec2 pp = uvVarying;")
	WriteLine(fw,"  vec3 col = mix(vec3(c, c, c), border.xyz, 0.6);")
	WriteLine(fw,"	vec3 col0 = mix(vec3 (texture2D(texture0, pp).rgb),col.xyz,0.6);")
	WriteLine(fw,"	//comment out line above and uncomment line below to remove the staticky look")
	WriteLine(fw,"	//vec3 col0 = mix(vec3 (texture2D(texture0, pp).rgb),border.xyz,0.6);")
	WriteLine(fw,"	gl_FragColor = vec4(col0, 1.0);")
	WriteLine(fw,"  }")
CloseFile(fw)
endfunction

function createRandomBgImage()
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    For num = 1 to 500
		DrawEllipse(Random(1,1023),Random(1,787),random(10,30),random(10,30),makecolor(random(1,255),random(1,255),random(1,255)),makecolor(random(1,255),random(1,255),random(1,255)),1)
    next num
    swap()
    img = getimage(0,0,1024,768)
    //SetImageTransparentColor(img,0,0,0)
endfunction img

works better if you use a proper model
if you look at the ps file there is a line that can be commented un commented to remove the staticky look
Posted: 2nd Jul 2019 23:16
That is nice ...could be used for some kinda hologram .

I made some test based on your first pixelate shader . I think could be done the camera depth with it ...this snipet needs some adjustements but here's what I have so far.


+ Code Snippet
SetErrorMode(2)

// set window properties
SetWindowTitle( "Pixelate" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

createShaderFile()
imgId=createRandomBgImage()
loadimage(2,"muros.png")
//CreateSprite(1,imgId)
for k= 1 to 10
LoadShader(k,"pixelate.vs","pixelate.ps")
next

for i= 1 to 10
	CreateObjectBox(i,5,5,5)
	SetObjectImage(i,2,0)
	SetObjectShader(i,i)
	setobjectposition(i,random(0,50),0,random(0,50))
next
//LoadSpriteShader(2, "pixelate.ps")
//SetSpriteShader( 1,2 )


x=10.0:y=10.0
do
for i= 1 to 10
		dx#=getobjectx(i)-getcamerax(1)
		dz#=getobjectz(i)-getcameraz(1)
		dist#=sqrt((dx#*dx#)+(dz#*dz#))
		kak=100-dist#*1.8
		if kak&lt;2 then kak=2
		SetShaderConstantByName(i,"pixels",kak,kak,0,0) //the bigger the numbers the more pixels
next
	   
    
    gosub camara
    
    print (ScreenFPS())
    sync()   
loop
camara:
	 if ( GetRawKeyState( 38 ) ) then MoveCameraLocalZ( 1, 1 )  // cursor up
	 if ( GetRawKeyState( 40 ) ) then MoveCameraLocalZ( 1, -1 ) // cursor down
	 if ( GetRawKeyState( 37 ) ) then MoveCameraLocalX( 1, -1 ) // cursor iz
	 if ( GetRawKeyState( 39 ) ) then MoveCameraLocalX( 1, 1 )  // cursor derecha 

	 if ( GetPointerPressed() )
		startx# = GetPointerX()
		starty# = GetPointerY()
		angx# = GetCameraAngleX(1)
		angy# = GetCameraAngleY(1)
		pressed = 1
	 endif

	 if ( GetPointerState() = 1 )
		fDiffX# = (GetPointerX() - startx#)/1.0
		fDiffY# = (GetPointerY() - starty#)/1.0

		newX# = angx# + fDiffY#
		if ( newX# &gt; 89 ) then newX# = 89
		if ( newX# &lt; -89 ) then newX# = -89
		SetCameraRotation( 1, newX#, angy# + fDiffX#, 0 )
	 endif
return

function createShaderFile()
fw = OpenToWrite("pixelate.vs")
WriteLine(fw,"attribute highp vec3 position;")
WriteLine(fw,"attribute mediump vec3 normal;")
WriteLine(fw,"attribute mediump vec2 uv;")
WriteLine(fw,"varying highp vec3 posVarying;")
WriteLine(fw,"varying mediump vec3 normalVarying;")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"varying mediump vec3 lightVarying;")
WriteLine(fw,"uniform highp mat3 agk_WorldNormal;")
WriteLine(fw,"uniform highp mat4 agk_World;")
WriteLine(fw,"uniform highp mat4 agk_ViewProj;")

WriteLine(fw,"uniform vec2 pixels; ")
WriteLine(fw,"uniform sampler2D texture0; // input channel")

WriteLine(fw,"uniform mediump vec4 uvBounds0;")
WriteLine(fw,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(fw,"void main()")
WriteLine(fw,"{") 
WriteLine(fw,"    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(fw,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(fw,"    gl_Position = agk_ViewProj * pos;")
WriteLine(fw,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(fw,"    posVarying = pos.xyz;")
WriteLine(fw,"    normalVarying = norm;")
WriteLine(fw,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(fw,"}") 
CloseFile(fw)

fw=OpenToWrite("pixelate.ps")
WriteLine(fw,"#ifdef GL_ES")
WriteLine(fw,"precision mediump float;")
WriteLine(fw,"precision mediump int;")
WriteLine(fw,"#endif")
WriteLine(fw,"#define PROCESSING_TEXTURE_SHADER")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"uniform sampler2D texture0;")
WriteLine(fw,"uniform vec2 pixels;")
WriteLine(fw,"void main(void)")
WriteLine(fw,"{")
WriteLine(fw,"  vec2 p = uvVarying;")
WriteLine(fw,"	p.x -= mod(p.x, 1.0 / pixels.x);")
WriteLine(fw,"	p.y -= mod(p.y, 1.0 / pixels.y);")
WriteLine(fw,"	vec3 col = texture2D(texture0, p).rgb;")
WriteLine(fw,"	gl_FragColor = vec4(col, 1.0);")
WriteLine(fw,"}")
CloseFile(fw)
endfunction

function createRandomBgImage()
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    For num = 1 to 500
		DrawEllipse(Random(1,1023),Random(1,787),random(10,30),random(10,30),makecolor(random(1,255),random(1,255),random(1,255)),makecolor(random(1,255),random(1,255),random(1,255)),1)
    next num
    swap()
    img = getimage(0,0,1024,768)
    //SetImageTransparentColor(img,0,0,0)
endfunction img




Posted: 2nd Jul 2019 23:32
That's quite interesting chafari
i didnt have muros.png so i used my own brick texture which might be different dimmensions
but i see the effect your creating. Could be good for an old retro game remake and using it
real time. I was originally thinking it might be good for an intro sequence where the objects
started off pixelated and slowly come into view at the beginning of the game. Then they could be
set to no shader so they revert back to default and no speed loss. Which could also be acheived
with a sprite shader but you couldnt have camera panning into the scene. Combined with your
effect could make for a great intro. VERY INTERESTING