Texture on a cube

BlitzMax Modules Forums/MiniB3D/Texture on a cube

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Yes, there is another way ;)

Use my modified (partly 0.42 ext) TTexture.bmx and recompile
the module.

TTexture.bmx
' Updates:
' 30/01/07 - AdjustPixmap

Type TTexture

	Global tex_list:TList=CreateList()

	Field file$,flags,blend=2,coords,u_scale#=1.0,v_scale#=1.0,u_pos#,v_pos#,angle#
	Field file_abs$,width,height ' returned by Name/Width/Height commands
	Field pixmap:TPixmap
	Field gltex[1]
	Field cube_pixmap:TPixmap[7]
	Field no_frames=1
	Field no_mipmaps
	Field cube_face=0,cube_mode=1
	
	Method FreeTexture()
	
		ListRemove(tex_list,Self)
		pixmap=Null
		cube_pixmap=Null
		gltex=Null
	
	End Method
	
	Function CreateTexture:TTexture(width,height,flags=1,frames=1,RenderTarget:Int = GL_RGBA)
	
		If flags&128 Then Return CreateCubeMapTexture(width,height,flags)
	
		Local tex:TTexture=New TTexture
		
		tex.pixmap=CreatePixmap(width*frames,height,PF_RGBA8888)

		' ***
		
		tex.flags=flags
		tex.FilterFlags()
				
		tex.no_frames=frames
		tex.gltex=tex.gltex[..tex.no_frames]

		' ***
		
		' pixmap -> tex
			
		Local x=0
	
		Local pixmap:TPixmap
	
		For Local i=0 To tex.no_frames-1
	
			pixmap=tex.pixmap.Window(x*width,0,width,height)
			x=x+1
		
			' ***
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height

			Local Name
			glGenTextures 1,Varptr Name
			glBindtexture GL_TEXTURE_2D,Name

			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level = 0
			
			Local Internal:Int
				Select RenderTarget
					Case GL_RGBA
						Internal = GL_RGBA8
					Case GL_DEPTH_COMPONENT
						Internal = GL_DEPTH_COMPONENT
				End Select
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				glTexImage2D GL_TEXTURE_2D,mip_level,Internal,tex.width,tex.height,0,RenderTarget,GL_UNSIGNED_BYTE,pixmap.pixels
				If Not mipmap Then Exit
				If tex.width=1 And tex.height=1 Exit
				If tex.width>1 tex.width:/2
				If tex.height>1 tex.height:/2

				pixmap=ResizePixmap(pixmap,tex.width,tex.height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level

			tex.gltex[i]=Name
	
		Next
		
		ListAddLast(tex_list,tex)
	
		Return tex

	End Function

	Function LoadTexture:TTexture(file:Object,flags=1)
	
		Return LoadAnimTexture:TTexture(file,flags,0,0,0,1)
	
	End Function
	
	Function LoadAnimTexture:TTexture(file2:Object,flags,frame_width,frame_height,first_frame,frame_count)
		Local file:Object = file2
		If flags&128 Then Return LoadCubeMapTexture(file,flags)

		Local tex:TTexture = New TTexture
		
		'()
		'DebugStop()
		file = Filefind(String(file))
		If File = Null Then 
			If TImage(file2) <> Null Then
				tex.file$="image"+tex_list.count()
				tex.file_abs$="//"
				
				' set tex.flags before TexInList
				tex.flags=flags
				tex.FilterFlags()
				
				Local old_tex:TTexture
				old_tex=tex.TexInList()
				If old_tex<>Null Then Return old_tex
		
				' load pixmap
				tex.pixmap = LockImage(TImage(file2) )
			ElseIf TPixmap(file2) <> Null Then
				tex.file$="pixmap"+tex_list.count()
				tex.file_abs$="//"
				
				' set tex.flags before TexInList
				tex.flags=flags
				tex.FilterFlags()
				
				Local old_tex:TTexture
				old_tex=tex.TexInList()
				If old_tex<>Null Then Return old_tex
		
				' load pixmap
				tex.pixmap = TPixmap(file2)
			Else
				Return Null
			EndIf
		Else
		
		'If FileFind(file)=False Then Return Null
		
			tex.file$=String(file)
			tex.file_abs$=FileAbs$(String(file))
			
			' set tex.flags before TexInList
			tex.flags=flags
			tex.FilterFlags()
			
			Local old_tex:TTexture
			old_tex=tex.TexInList()
			If old_tex<>Null Then Return old_tex
	
			' load pixmap
			tex.pixmap = LoadPixmap(file)
		EndIf
		
		If tex.pixmap = Null Then Return
		' convert pixmap to appropriate format
		If tex.pixmap.format<>PF_RGBA8888
			tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
		EndIf
		
		' ***
		
		' if tex not anim tex, get frame width and height
		If frame_width=0 And frame_height=0
			frame_width=tex.pixmap.width
			frame_height=tex.pixmap.height
		EndIf

		' ***
		
		'tex.flags=flags
		'tex.FilterFlags()
		
		tex.no_frames=frame_count
		tex.gltex=tex.gltex[..tex.no_frames]

		' ***
		
		' pixmap -> tex

		Local xframes=tex.pixmap.width/frame_width
		Local yframes=tex.pixmap.height/frame_height
			
		Local startx=first_frame Mod xframes
		Local starty=(first_frame/yframes) Mod yframes
			
		Local x=startx
		Local y=starty
	
		Local pixmap:TPixmap
	
		For Local i=0 To tex.no_frames-1
	
			' get static pixmap window. when resize pixmap is called new pixmap will be returned.
			pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
			x=x+1
			If x>=xframes
				x=0
				y=y+1
			EndIf
		
			' ***
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height

			Local Name
			glGenTextures 1,Varptr Name
			glBindtexture GL_TEXTURE_2D,Name

			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level=0
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
				If Not mipmap Then Exit
				If tex.width=1 And tex.height=1 Exit
				If tex.width>1 tex.width:/2
				If tex.height>1 tex.height:/2

				pixmap=ResizePixmap(pixmap,tex.width,tex.height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level

			tex.gltex[i]=Name
	
		Next
		
		ListAddLast(tex_list,tex)
		TGlobal.Errorhandler.CheckError("TTextrue.bmx",204)
	   	TGlobal.ErrorHandler.SendMsg("texture '"+String(file)+" succesfully loaded")

		Return tex
		
	End Function

	Function CreateCubeMapTexture:TTexture(width,height,flags)

		Local tex:TTexture=New TTexture
		
		tex.pixmap=CreatePixmap(width*6,height,PF_RGBA8888)

		' ***
		
		tex.flags=flags
		'tex.FilterFlags()
				
		tex.no_frames=1'frame_count
		'tex.gltex=tex.gltex[..tex.no_frames]

		' ***
		
		' pixmap -> tex
				
		Local Name
		glGenTextures 1,Varptr Name
		glBindtexture GL_TEXTURE_CUBE_MAP,Name
	
		Local pixmap:TPixmap
	
		For Local i=0 To 5
		
			pixmap=tex.pixmap.Window(width*i,0,width,height)

			' ***
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height

			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level=0
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				Select i
					Case 0 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_X,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 1 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Z,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 2 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_X,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 3 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 4 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Y,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 5 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
				End Select
				If Not mipmap Then Exit
				If tex.width=1 And tex.height=1 Exit
				If tex.width>1 tex.width:/2
				If tex.height>1 tex.height:/2

				pixmap=ResizePixmap(pixmap,tex.width,tex.height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level
			
		Next
		
		tex.gltex[0]=Name
		ListAddLast(tex_list,tex)
		
		Return tex
		
	End Function

	Function LoadCubeMapTexture:TTexture(file:Object,flags=1)
	
		Local tex:TTexture=New TTexture
		
		'If FileFind(String(file))=False Then Return Null
		
		tex.file$=String(file)
		tex.file_abs$=FileAbs$(String(file))
		
		' set tex.flags before TexInList
		tex.flags=flags
		tex.FilterFlags()
		
		Local old_tex:TTexture
		old_tex=tex.TexInList()
		If old_tex<>Null Then Return old_tex

		' load pixmap
		tex.pixmap=LoadPixmap(file)

		' convert pixmap to appropriate format
		If tex.pixmap.format<>PF_RGBA8888
			tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
		EndIf
		
		' ***
		
		' get tex width,height

		Local width=tex.pixmap.width/6
		Local height=tex.pixmap.height

		' ***
		
		'tex.flags=flags
		'tex.FilterFlags()
				
		tex.no_frames=1'frame_count
		'tex.gltex=tex.gltex[..tex.no_frames]
		
		' ***
		
		' pixmap -> tex
			
		Local Name
		glGenTextures 1,Varptr Name
		glBindtexture GL_TEXTURE_CUBE_MAP,Name
	
		Local pixmap:TPixmap
	
		For Local i=0 To 5
		
			pixmap=tex.pixmap.Window(width*i,0,width,height)

			' ***
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height

			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level=0
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				Select i
					Case 0 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_X,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 1 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Z,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 2 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_X,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 3 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 4 glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Y,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
					Case 5 glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,mip_level,GL_RGBA8,tex.width,tex.height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
				End Select
				If Not mipmap Then Exit
				If tex.width=1 And tex.height=1 Exit
				If tex.width>1 tex.width:/2
				If tex.height>1 tex.height:/2

				pixmap=ResizePixmap(pixmap,tex.width,tex.height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level
			
		Next
		
		tex.gltex[0]=Name
		ListAddLast(tex_list,tex)
	
		Return tex

	End Function

	Method TextureBlend(blend_no)
		
		blend=blend_no
		
	End Method
	
	Method TextureCoords(coords_no)
	
		coords=coords_no
	
	End Method
	
	Method ScaleTexture(u_s#,v_s#)
	
		u_scale#=1.0/u_s#
		v_scale#=1.0/v_s#
	
	End Method
	
	Method PositionTexture(u_p#,v_p#)
	
		u_pos#=-u_p#
		v_pos#=-v_p#
	
	End Method
	
	Method RotateTexture(ang#)
	
		angle#=ang#
	
	End Method
	
	Method TextureWidth()
	
		Return width
	
	End Method
	
	Method TextureHeight()
	
		Return height
	
	End Method
	
	Method TextureName$()
	
		Return file_abs$
	
	End Method
	
	Function GetBrushTexture:TTexture(brush:TBrush,index=0)
	
		Return brush.tex[index]
	
	End Function
	
	Function ClearTextureFilters()
	
		ClearList TTextureFilter.filter_list
	
	End Function
	
	Function TextureFilter(match_text$,flags)
	
		Local filter:TTextureFilter=New TTextureFilter
		filter.text$=match_text$
		filter.flags=flags
		ListAddLast(TTextureFilter.filter_list,filter)
	
	End Function
	
	Method SetCubeFace(face)
		cube_face=face
	End Method
	
	Method SetCubeMode(mode)
		cube_mode=mode
	End Method
	
	' MiniB3D functions
	
	' Essential - offers Blitz3D functionality that cannot be exactly matched

	Method BackBufferToTex(mipmap_no=0,frame=0)
	
		Local x=0,y=0
	
		glBindtexture GL_TEXTURE_2D,gltex[frame]
		glCopyTexImage2D(GL_TEXTURE_2D,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)

	End Method
	
	
	Method BackBufferToTexExt(mipmap_no=0,frame=0,Kind=GL_RGBA)
		Local x=0,y=0
		glBindtexture GL_TEXTURE_2D,gltex[frame]
		glCopyTexImage2D(GL_TEXTURE_2D,mipmap_no,Kind,x,TGlobal.height-y-height,width,height,0)
		'gluBuild2DMipmaps(GL_TEXTURE_2D, 4,pixmap.width,pixmap.height,Kind, GL_UNSIGNED_BYTE, pixmap.pixels)
	End Method

	
	Method BackBufferToCubeTex(mipmap_no=0)
	
		Local x=0,y=0
	
		glBindtexture GL_TEXTURE_CUBE_MAP_EXT,gltex[0]
		Select cube_face
			Case 0 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
			Case 1 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
			Case 2 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
			Case 3 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
			Case 4 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
			Case 5 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
		End Select

	End Method
	
	' Extra - offers extra functionality that Blitz3D does not
	
	Method CountMipmaps()
		Return no_mipmaps
	End Method
	
	Method MipmapWidth(mipmap_no)
		If mipmap_no>=0 And mipmap_no<=no_mipmaps
			Return width/(mipmap_no+1)
		Else
			Return 0
		EndIf
	End Method
	
	Method MipmapHeight(mipmap_no)
		If mipmap_no>=0 And mipmap_no<=no_mipmaps
			Return height/(mipmap_no+1)
		Else
			Return 0
		EndIf
	End Method
	
	' Internal - not recommended for general use
	
	Function FileFind:Object(file2:Object)
		Local file:String = String(File2)
		Local fback:String = file
		Local isIncbin:Byte = False
		
		If file[..6] = "incbin" Then IsIncbin = True
		
		If FileType(file)=0
			Repeat
				If isIncbin = True Then 
					file$="incbin::" + Right$(file$,(Len(file$)-Instr(file$,"",1)))
				Else
					file$ = Right$(file$ , (Len(file$) - Instr(file$ , "" , 1) ) )
				EndIf
			Until Instr(file$,"",1)=0
			Repeat
				file$ = Right$(file$ , (Len(file$) - Instr(file$ , "/" , 1) ) )
			Until Instr(file$ , "/" , 1) = 0
			
			If IsIncbin = False Then
				If FileType(file$)=0
					DebugLog "ERROR: Cannot find texture: "+file$
					Return Null
				EndIf
			Else
				If ReadStream(File) = Null Then
					DebugLog "ERROR: Cannot find texture: "+file$
					Return Null
				EndIf	
			EndIf
		EndIf
		
		Return file
		
	End Function
	
	Function FileAbs$(file$)
	
		Local file_abs$
	
		If Instr(file$,":")=False
			file_abs$=CurrentDir$()+"/"+file$
		Else
			file_abs$=file$
		EndIf
		file_abs$=Replace$(file_abs$,"","/")
		
		Return file_abs$
	
	End Function
		
	Method TexInList:TTexture()
	
		' check if tex already exists in list and if so return it

		For Local tex:TTexture=EachIn tex_list
			If file$=tex.file$ And flags=tex.flags
				Return tex
			EndIf
		Next
	
		Return Null
	
	End Method
	
	Method FilterFlags()
	
		' combine specifieds flag with texture filter flags
		For Local filter:TTextureFilter=EachIn TTextureFilter.filter_list
			If Instr(file$,filter.text$) Then flags=flags|filter.flags
		Next
	
	End Method
		
	Function AdjustPixmap:TPixmap(pixmap:TPixmap)
	
		' adjust width and height size to next biggest power of 2 size
		Local width=Pow2Size(pixmap.width)
		Local height=Pow2Size(pixmap.height)

		' check that width and height size are valid (not too big)
		Repeat
			Local t
			glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
			glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
			If t Exit
			If width=1 And height=1 RuntimeError "Unable to calculate tex size"
			If width>1 width:/2
			If height>1 height:/2
		Forever

		' if width or height have changed then resize pixmap
		If width<>pixmap.width Or height<>pixmap.height
			pixmap=ResizePixmap(pixmap,width,height)
		EndIf
		
		' return pixmap
		Return pixmap
		
	End Function
	
	Function Pow2Size( n )
		Local t=1
		While t<n
			t:*2
		Wend
		Return t
	End Function
	
	Rem
	Function AdjustPixmap:TPixmap(pixmap:TPixmap)
	
		Local width=Pow2Size(pixmap.width)
		Local height=Pow2Size(pixmap.height)

		If width<>pixmap.width Or height<>pixmap.height
			pixmap=ResizePixmap(pixmap,width,height)
		EndIf
		
		Return pixmap
		
	End Function
	
	Function Pow2Size( n )
		Local t=1
		While t<n
			t:*2
		Wend
		Return t
	End Function
	End Rem
End Type

Type TTextureFilter

	Global filter_list:TList=CreateList()

	Field text$
	Field flags
	
End Type


And in func.bmx change the LoadTexture Function to this:
Function LoadTexture:TTexture(file:Object,flags=1)
	Return TTexture.LoadTexture(file,flags)
End Function


After rebuilding the module you should normally be able to load Textures which are incbin, TImage or TPixmap .