Code archives/3D Graphics - Misc/Pixies 2

This code has been declared by its author to be Public Domain code.

Download source code

Pixies 2 by Moore2011
- This code allows you to load a texture with a mask.
- Create a texture with the infamous flag 4 (masking) working.
- Allows you to remask an existing texture with the color of your choice
- Supports animated textures and textures of odd sizes
; Pixies 2 Created by NRMStudios
; NRMStudios@gmail.com

; Based on "pixies.bb"
; by skidracer

; Improvements
; Animation Support
; Masking Support

; Graphics3D 800,600 ; for demo

Global pixies_mask_texture = CreateTexture(1024,1024,4)
Global pixies_mask_size = 1024
mask_texture(pixies_mask_texture)

;DEMO =========================================================================================================

;	camera = CreateCamera()
;	CameraClsColor camera, 0,100,0 ; makes background green instead of black
;	
;	
;	; Create sprite
;	sprite = CreatePixie(camera, 128, 128, 5, 2)
;	brush = GetEntityBrush(sprite)
;	t = GetBrushTexture(brush) ; get the texture
;	image = CreateImage(128,128,2)
;	
;	; add a red circle to the first frame
;	SetBuffer ImageBuffer(image, 0)
;	;SetBuffer TextureBuffer(t, 0)
;	Color 255,0,0
;	Oval 10, 10, 100, 100, True
;	Color 1,0,0
;	Oval 10, 10, 100, 100, False
;	Color 0,255,0
;	Text 50,50, "HELLO!", True, True
;	; add a blue circle to the second frame
;	SetBuffer ImageBuffer(image, 1)
;	;SetBuffer TextureBuffer(t, 1)
;	Color 0,0,255
;	Oval 10, 10, 100, 100, True
;	Color 1,0,0
;	Oval 10, 10, 100, 100, False
;	Color 255,255,255
;	Text 50,50, "HELLO!", True, True
;	
;	CopyRect 0,0,128,128,0,0,ImageBuffer(image,0),TextureBuffer(t,0) 
;	CopyRect 0,0,128,128,0,0,ImageBuffer(image,1),TextureBuffer(t,1)
;	mask_texture(t,128,128,2) 
;	FreeImage image
;	
;	; position entity on the screen
;	PositionEntity sprite, 400,200, 0
;
;	; load an animated sprite, image is 100x50 of two triangles each being 50x50 with a black masking
;	sprite2 = LoadAnimPixie(camera,"triangle.png", 50, 50, 5)
;	PositionEntity sprite2, 50, 50, 0
;	
;	sprite3 = LoadPixie(camera,"triangle.png", 5)
;	PositionEntity sprite3, 50, 150, 0
;	
;	
;	time = MilliSecs()
;	While Not KeyHit(1)
;		; Timer to animate the image
;		If MilliSecs() - time > 1000 Then
;			time = MilliSecs()
;			If frame = 1 Then frame = 0 Else frame = 1 ; advance the frame
;			EntityTexture sprite, t, frame ; update the entity texture
;		EndIf
;		
;		SetBuffer BackBuffer()
;		RenderWorld()
;		Flip
;	Wend
;	
;	End
;	
; End of demo =================================================================================================================================

Function mask_texture(t, frames = 1, mask_color = 0); ...................................................................... mask_texture
; Drops the alpha of all pixels that match the masking color to 0
	w = TextureWidth(t)
	h = TextureHeight(t)
	For fi = 0 To frames - 1
		buffer = TextureBuffer(t, fi)
		LockBuffer buffer
		For iw = 0 To w - 1
			For ih = 0 To h - 1
				c = ReadPixelFast(iw, ih, buffer) And $FFFFFF 		; Read pixel from texture
				If c = mask_color 									; If Color = mask_color
					WritePixelFast iw, ih, 0, buffer 				; Write transparent black pixel
				Else 												; If color != mask_color
					WritePixelFast iw, ih, c Or $FF000000, buffer 	; Write color and 100% alpha to texture
				End If
			Next
		Next
		UnlockBuffer buffer
	Next 
End Function

Function SaveAnimImage(file$, img, frames = 1, states = 1) ; ..................................................................... SaveAnimImage
; This function is NOT needed for pixies to work.
	w = ImageWidth(img)
	h = ImageHeight(img)
	image = CreateImage(w*frames,h*states)
	For ii = 0 To states - 1
		For i = 0 To frames - 1
			CopyRect 0, 0, w, h, i * w, ii * h, ImageBuffer(img,i), ImageBuffer(image)
		Next
	Next
	chk = SaveImage(image, file)
	FreeImage image
	Return chk
End Function

Function flush_texture(t, frames = 1)
; Fast way to set the alpha of all pixels in a texture to 0 using copyrect

	w = TextureWidth(t)
	h = TextureHeight(t)
	size = w
	If h > size Then size = h
	
	; adjust size of blank mask as needed
	If pixies_mask_size < size Then
		While pixies_mask_size < size
			pixies_mask_size = pixies_mask_size * 2
		Wend
		FreeTexture pixies_mask_texture
		pixies_mask_texture = CreateTexture(pixies_mask_size, pixies_mask_size, 5)
		mask_texture(pixies_mask_texture, pixies_mask_size, pixies_mask_size)
	EndIf
	
	For i = 0 To frames - 1
		CopyRect 0,0,w,h,0,0,TextureBuffer(pixies_mask_texture), TextureBuffer(t,i)
	Next
End Function

Function CreatePixie(camera, w#, h#, flags=1, frames=1, viewwidth# = 0, viewheight# = 0) ; CreatePixie
	; load squared texture
	
	texture = CreateTexture(w,h,flags,frames)
	width = TextureWidth(texture)
	height = TextureHeight(texture)
	
	If w<>width Or h<>height
		For i = 0 To frames - 1
			If (flags And (1 Shl 2)) <> 0 Then ; if image is masked
				flush_texture(texture, frames) ; flush the alpha value from the texture 
			Else ; image is not masked
				SetBuffer TextureBuffer(texture, i) ; provide a plain black background with full alpha
				Color 255,255,255
				Rect 0,0,iwidth,iheight,True
			EndIf
		Next
	
		ScaleTexture texture,Float(width)/w,Float(height)/h ; will blitzmax need float()?
		width=w
		height=h
	ElseIf (flags And (1 Shl 2)) <> 0 Then
		flush_texture(texture, frames)
	EndIf
	
	; change these for viewports
	If viewwidth = 0 Then viewwidth = GraphicsWidth()
	If viewheight = 0 Then viewheight = GraphicsHeight()
	
	; find existing pixiespace parented to camera
	magic=0
	n=CountChildren(camera)
	For i=1 To n
		If EntityName(GetChild(camera,i))="pixiespace" 
			magic=GetChild(GetChild(camera,i),1)
		EndIf
	Next
	If magic=0
		magic=CreatePivot(camera) 
		NameEntity(magic,"pixiespace")
		aspect# = (viewheight/viewwidth) 			;aspect# = viewheight/viewwidth
		PositionEntity magic,-1,aspect,1			;PositionEntity magic,-1,aspect,1
		scale#=(2.0/viewwidth) 						;scale# = 2.0/viewwidth
		ScaleEntity magic,scale,-scale,-scale 
		magic=CreatePivot(magic)
		PositionEntity magic,-.5,-.5,0 				;PositionEntity magic,-.5,-.5,0
	EndIf
	
	; create sprite from texture as child of magic overlay	
	sprite=CreateSprite()
	EntityParent sprite,magic		;cludge for blitz bug in createsprite(parent)
	brush=CreateBrush()
	BrushFX brush,1
	BrushTexture brush,texture
	PaintEntity sprite,brush
	FreeBrush brush
	SpriteViewMode sprite,2 
	scale#=1.0/viewwidth 
	ScaleSprite sprite,width*scale,height*scale
	Return sprite
End Function

Function LoadAnimPixie(camera,file$, w#, h#, flgs = 1, count = 0, frst=0, viewwidth# = 0, viewheight# = 0)
; load squared texture
	image=LoadImage(file)
	iwidth#=ImageWidth(image)
	iheight#=ImageHeight(image)
	If count = 0 Then 
		count = (iwidth/w)*(iheight/h)
	EndIf
	FreeImage image
	image = LoadAnimImage(file, w, h, frst, count)
	iwidth = ImageWidth(image)
	iheight = ImageHeight(image)
	texture=LoadAnimTexture(file, flgs, w, h, frst, count)
	width#=TextureWidth(texture)
	height#=TextureHeight(texture)
	
	For i = 0 To count - 1
		If iwidth<>width Or iheight<>height
			CopyRect 0,0,iwidth,iheight,0,0,ImageBuffer(image,i), TextureBuffer(texture,i) 
			
			ScaleTexture texture, width / (w), height / (h)
			width=iwidth
			height=iheight
		EndIf
	Next

	If (flgs And (1 Shl 2)) <> 0 Then mask_texture(texture, count)
	
	FreeImage image

	; change these for viewports
	If viewwidth = 0 Then viewwidth = GraphicsWidth()
	If viewheight = 0 Then viewheight = GraphicsHeight()
	
; find existing pixiespace parented to camera
	magic=0
	n=CountChildren(camera)
	For i=1 To n
		If EntityName(GetChild(camera,i))="pixiespace" 
			magic=GetChild(GetChild(camera,i),1)
		EndIf
	Next
	If magic=0
		magic=CreatePivot(camera) 
		NameEntity(magic,"pixiespace")
		aspect# = (viewheight/viewwidth) 			;aspect# = viewheight/viewwidth
		PositionEntity magic,-1,aspect,1			;PositionEntity magic,-1,aspect,1
		scale#=(2.0/viewwidth) 						;scale# = 2.0/viewwidth
		ScaleEntity magic,scale,-scale,-scale 
		magic=CreatePivot(magic)
		PositionEntity magic,-.5,-.5,0 				;PositionEntity magic,-.5,-.5,0
	EndIf
	
; create sprite from texture as child of magic overlay	
	sprite=CreateSprite()
	EntityParent sprite,magic		;cludge for blitz bug in createsprite(parent)
	brush=CreateBrush()
	BrushFX brush,1
	BrushTexture brush,texture
	PaintEntity sprite,brush
	FreeBrush brush
	SpriteViewMode sprite,2 
	scale#=1.0/viewwidth 
	ScaleSprite sprite,width*scale,height*scale
	Return sprite
End Function

Function LoadPixie(camera,file$, flags)
; load squared texture
	texture=LoadTexture(file, flags)
	width#=TextureWidth(texture)
	height#=TextureHeight(texture)
	image=LoadImage(file)
	iwidth#=ImageWidth(image)
	iheight#=ImageHeight(image)

	If iwidth<>width Or iheight<>height
		SetBuffer TextureBuffer(texture)
		
		CopyRect 0,0,iwidth,iheight,0,0,ImageBuffer(image), TextureBuffer(texture)
	
		ScaleTexture texture,Float(width)/iwidth,Float(height)/iheight ; will blitzmax need float()?
		width=iwidth
		height=iheight
	EndIf

	FreeImage image
	
	If (flags And (1 Shl 2)) <> 0 Then mask_texture(Texture, width, height)
	
; change these for viewports
	viewwidth#=GraphicsWidth()
	viewheight#=GraphicsHeight()
	
; find existing pixiespace parented to camera
	magic=0
	n=CountChildren(camera)
	For i=1 To n
		If EntityName(GetChild(camera,i))="pixiespace" 
			magic=GetChild(GetChild(camera,i),1)
		EndIf
	Next
	If magic=0
		magic=CreatePivot(camera) 
		NameEntity(magic,"pixiespace")
		aspect# = (viewheight/viewwidth) 			;aspect# = viewheight/viewwidth
		PositionEntity magic,-1,aspect,1			;PositionEntity magic,-1,aspect,1
		scale#=(2.0/viewwidth) 						;scale# = 2.0/viewwidth
		ScaleEntity magic,scale,-scale,-scale 
		magic=CreatePivot(magic)
		PositionEntity magic,-.5,-.5,0 				;PositionEntity magic,-.5,-.5,0
	EndIf
	
; create sprite from texture as child of magic overlay	
	sprite=CreateSprite()
	EntityParent sprite,magic		;cludge for blitz bug in createsprite(parent)
	brush=CreateBrush()
	BrushFX brush,1
	BrushTexture brush,texture
	PaintEntity sprite,brush
	FreeBrush brush
	SpriteViewMode sprite,2 
	scale#=1.0/viewwidth 
	ScaleSprite sprite,width*scale,height*scale
	Return sprite
End Function

Comments

_PJ_2011
I haven't yet checked this out properly, but the fix for Masking is a godsend :)


Code Archives Forum