Texture a random shape.
Blitz3D Forums/Blitz3D Beginners Area/Texture a random shape.
| ||
| How could I apply a scaled, rotated texture to a random shape created with Drawline? For example... Graphics 640,480 setbuffer backbuffer() Line 10,10,400,10 Line 400,10,400,200 wLine 400,200,300,200 Line 300,200,350,150 Line 350,150,10,10 Flip WaitKey() Thanks |
| ||
| I'm going to assume you're used to Blitzmax :P In blitz3d there is no *quick* way to do it- You could however, use copypixel to do it.... Though as i said--- itl be slow. Certainly not realtime... |
| ||
| Hi Cygnus, Thanks for the reply. I've done it in BlitzMax using OGL. I didn't think there was an easy answer so I'll continue using floodfill/wpf for the shapes. |
| ||
you could always do the following, which works perfect for me for creating internal textures and images.
Graphics3D 640,480
setbuffer backbuffer()
Global Mesh=LoadMesh("object name")
Global Texture=createtexture(Size,Size,Flags) ; size being 64,128, 256 etc - and flags is optional, remove if unneeded
setbuffer TextureBuffer(Texture)
Line 10,10,400,10
Line 400,10,400,200
Line 400,200,300,200
Line 300,200,350,150
Line 350,150,10,10
setbuffer backbuffer()
; rest of program
And then assign it to your mesh / object - with EntityTexture Mesh,Texture Hope this helps ya matey, Cheers - Clyde :) |
| ||
| @tonyg: you talk about applying texture, this is 3D terminology but you are using 2D commands. Perhaps you should be using sprites or quads?? Rhy :) |
| ||
| Hi Clyde, I *think* that will take an 'object' and apply a texture of the poly drawn with the lines.. Is that right? What I need to do is draw a shape (possible any shape with any number of sides) and then apply a loaded texture ONLY to that shape. I could... a) Draw the shape on black background b) Floodfill the shape with 255,0,255 c) Grab the resulting image. d) maskimage 255,255,255 (or 0,0,0) e) Draw the texture f) Draw the shape image g) Grab the resulting image. In Blitzmax I can apply a texture using Triangle_strip or GL_Polygon with vertex commands. Rhy, this *is* 2D line statements but with the limitations above. It needs to be quite quick which is why the above is not viable. |
| ||
| Soz mate, I thought you were after texturing an object by creating one internally. Are you after creating a random model? Im not too hot at making objects, especially within B3D. I'd suggest investigating CreateMesh, AddTriangle and AddVertex. There were some examples of various custom mesh making in the Code Archives. Sorry I couldnt of been of more help, hope it puts you on the right path. Cheers and good luck dude, Clyde :) |
| ||
| Hmmm, I am confused - probably because I do not know BlitzMax! At the risk of making a fool of myself, I will have another bash ;) You said 'In Blitzmax I can apply a texture using Triangle_strip or GL_Polygon with vertex commands'. Vertex commands are 3D, used to create the vertices of a 3D mesh. I was suggesting you create a flat 3D object by creating a vertex at each corner then linking them up with triangles. You can then apply your loaded texture (Global Texture=createtexture(Size,Size,Flags)) to the 3D surface you have just created. You can not apply textures to a 2D shape, as that 'shape' does not actualy exist (it is just a collection of pixels on the screen). Sorry if you know all that, Rhy :) |
| ||
| Hi Rhy, As Blitzmax is (really) all 3D when you use Drawpoly it takes the points and uses them in a gl_polygon command as vertex2f commands (2D float) which you can bind the texture to. What you're suggesting sounds very similar. Given a list of points, how would I create the flat 3D object and then use (I assume) texturecoord to texture that shape. Don't I need a surface ID (or something) to assing texturecoords and a texture to? I know little about 3D so it's probably me missing something obvious. |
| ||
| You may find using sprites is the easiest (check out the 'Sprite' commands in the Blitz3D help - hit F2 or F1 twice in the default IDE, I think!). Sprites are flat 3D entities and are square in shape, but your texture can always contain transparent areas to create the look of more complex objects - depends what you need. They are easy to use and can be set (default) to always face the camera (you always need a camera and lights to view 3D objects). However, creating your own quads is more flexible and faster (but more complicated). Check out this code I found by quickly looking in the code archives. I am not saying these are the best for you, but they look ok from a quick read through and you should be able to modify for your own needs. If all you need is a square, you only need 4 vertices and 2 triangles (a quad). http://www.blitzbasic.com/codearcs/codearcs.php?code=463 http://www.blitzbasic.com/codearcs/codearcs.php?code=382 I learnt an awful lot by studying other peoples code, so always worth browsing the archives (and forums). 3D is a big topic, I am still learning after having Blitz3D for nearly 2 years! Have fun, Rhy EDIT: Oh, and once you have your quad or sprite, you will apply your texture to it using EntityTexture. You will need to store handle of the quad or sprite in a variable which you pass to EntityTexture (see Blitz help). You can adjust texture position using UV coordinates (do a search, I am sure you find exisiting info on this). |
| ||
| Hmmm, here is a quick snippet of code off the top of my head, should make my waffling above a bit clearer!!?? I am not guaranteeing this will work, but it should give you a basic framework :) You will need to experiment with entity position in realtion to camera so that you can 'see' the sprite. Remember, you are creating a 3D 'world', NOT drawing to the screen. Camera = CreateCamera() Light = CreateLight(2) Mesh = CreateSprite() Texture = createtexture(Size,Size,Flags) EntityTexture (Mesh, Texture) PositionEntity(Mesh, 0, 0, 10) while keyhit(1) <> 1 renderworld() flip wend end |
| ||
| Doh, another post!! I am tired, sorry ;) To create a texture, you could use the code 'Clyde' suggested above. Alternativley create a texture in your favourite paint program and use 'LoadTexture' instead of 'CreateTexture'. Textures must be square and in powers of 2 (ie. 32x32, 64x64, 128x128 pixels etc). To start with, the easiest to get it up and running is just use 'EntityColor' instead of applying a texture at all. |
| ||
| I think what you're saying is there is no way of doing this with the pure 2D side of 3D. Just in case, this is the 'hack' I have so far.
Graphics 640,480
SetBuffer BackBuffer()
Global msx#,msy#,point1,point2,hi_angle#=-1000,lo_angle#=1000,hi_circ_x#,hi_circ_y#,lo_circ_x#,lo_circ_y#
Global hi_pty#,hi_ptx#,lo_pty#,lo_ptx#, msxhi#, msxlo#, hi_msx#, hi_msy#, lo_msy# , lo_msx#
Global Intersection_X# ; Values returned by the Lines_Intersect() function.
Global Intersection_Y#
Global Intersection_AB#
Global Intersection_CD#
rgb = getrgb(40,40,40)
;[needed for flood fill]
Dim map(GraphicsWidth(),GraphicsHeight())
Dim stackx(GraphicsWidth()*GraphicsHeight())
Dim stacky(GraphicsWidth()*GraphicsHeight())
Dim xmove(4),ymove(4)
xmove(1)=+1
xmove(3)=-1
ymove(2)=+1
ymove(4)=-1
;[/needed]
While Not KeyHit(1)
ClsColor 60,255,60
Cls
msx# = MouseX()
msy# = MouseY()
Color 255,255,255
Oval msx-100,msy-100,200,200,1
Color 0,0,0
Oval msx-4,msy-4,8,8
pt1x = 360 : pt1y = 280 : pt2x = 380 : pt2y = 320
Color 40,40,40
line_extend(pt1x,pt1y,msx,msy)
line_extend(pt2x,pt2y,msx,msy)
line_extend(pt1x,pt2y,msx,msy)
line_extend(pt2x,pt1y,msx,msy)
Line hi_ptx,hi_pty,hi_msx+hi_circ_x,hi_msy+hi_circ_y
Line lo_ptx,lo_pty,lo_msx+lo_circ_x,lo_msy+lo_circ_y
Line hi_ptx,hi_pty,lo_ptx,lo_pty
lines_intersect(hi_ptx,hi_pty,lo_msx+lo_circ_x,lo_msy+lo_circ_y,lo_ptx,lo_pty,hi_msx+hi_circ_x,hi_msy+hi_circ_y)
If ((msx-intersection_x)*(msx-intersection_x))+((msy-intersection_y)*(msy-intersection_y)) <= 10000
fillfast(Intersection_X#,Intersection_y#,rgb,BackBuffer())
EndIf
Color 0,0,255
Rect pt1x,pt1y,pt2x-pt1x,pt2y-pt1y
Text 100,0,"low angle = " + lo_angle
Text 100,10,"High angle = " + hi_angle
curTime = MilliSecs()
If curTime > checkTime Then
checkTime = curTime + 1000
curFPS = fpscounter
fpscounter = 0
Else
fpscounter = fpscounter + 1
End If
Text 100,20,"FPS : " + curFPS
Flip
hi_angle = -1000
lo_angle = 1000
Wend
Function line_extend(point1,point2,msx1,msy1)
If ((msx1-point1)*(msx1-point1))+((msy1-point2)*(msy1-point2)) <= 10000
angle = ATan2(msx1-point1,msy1-point2)
If angle > hi_angle
hi_angle = angle
hi_circ_x# = -Sin(hi_angle)*100
hi_circ_y# = -Cos(hi_angle)*100
hi_msx = msx1
hi_msy = msy1
hi_ptx = point1
hi_pty = point2
EndIf
If angle < lo_angle
lo_angle = angle
lo_circ_x# = -Sin(lo_angle)*100
lo_circ_y# = -Cos(lo_angle)*100
lo_msx = msx1
lo_msy = msy1
lo_ptx = point1
lo_pty = point2
EndIf
EndIf
End Function
Function GetRGB% ( Red% , Green% , Blue% ) ; Combines Red, Green and Blue values into one RGB value
Return Red Shl 16 + Green Shl 8 + Blue
End Function
Function fillfast(startx,starty,fillc,buffer)
scx=GraphicsWidth()
scy=GraphicsHeight()
If startx<0 Or starty<0 Or startx>=scx Or starty>=scy Then RuntimeError "fill starting point out of bounds"
fillover=ReadPixelFast(startx,starty)
If fillover=fillc Then Return
LockBuffer buffer
Dim map(scx,scy)
WritePixelFast startx,starty,fillc
map(startx,starty)=-1
stackx(1)=startx
stacky(1)=starty
i2=1
Repeat
i=i+1
If i>i2 Then Exit
For dir=1 To 4
If map(stackx(i),stacky(i))<>dir Then
x=stackx(i)+xmove(dir)
y=stacky(i)+ymove(dir)
If x>=0 And y>=0 And x<scx And y<scy Then
If map(x,y)=0 Then
If ReadPixelFast(x,y)=fillover Then
map(x,y)=dir+2-(dir+2>4) Shl 2
i2=i2+1
stackx(i2)=x
stacky(i2)=y
WritePixelFast x,y,fillc
EndIf
EndIf
EndIf
EndIf
Next
Forever
UnlockBuffer buffer
End Function
Function Lines_Intersect(Ax#, Ay#, Bx#, By#, Cx#, Cy#, Dx#, Dy#)
Rn# = (Ay#-Cy#)*(Dx#-Cx#) - (Ax#-Cx#)*(Dy#-Cy#)
Rd# = (Bx#-Ax#)*(Dy#-Cy#) - (By#-Ay#)*(Dx#-Cx#)
If Rd# = 0
; Lines are parralel.
; If Rn# is also 0 then lines are coincident. All points intersect.
; Otherwise, there is no intersection point.
Return False
Else
; The lines intersect at some point. Calculate the intersection point.
Sn# = (Ay#-Cy#)*(Bx#-Ax#) - (Ax#-Cx#)*(By#-Ay#)
Intersection_AB# = Rn# / Rd#
Intersection_CD# = Sn# / Rd#
Intersection_X# = Ax# + Intersection_AB#*(Bx#-Ax#)
Intersection_Y# = Ay# + Intersection_AB#*(By#-Ay#)
Return True
EndIf
End Function
<some of the code has been taken from examples on bb and bc so thanks and apologies for no credits). It's, basically, a shadow caster with a lot of stuff hard-coded at the moment. Lines are traces from the centre of the light (black oval in big white oval) to each predetermined edge of the rectangle. The lines are then checked to cast a shadow by taking the points of the furthest intersections and using floodfill to make the resulting 'shape' black. There's quite a few bugs (such as the flip at 180 degress) which can be worked out later. What I really want to do is fill that shadow shape as quickly as possible. |
| ||
| Nice effect :) Unless what you are doing is going to develop into a 'true' 3D application, then what you are doing seems fine. As far as I know, using WritePixelFast is the quickest way to fill an area. Just to answer all your questions, there are other ways of doing this using the 3D commands of Blitz3D. However, Blitz3D is NOT just 3D and contains a comprehensive 2D command set also, which is what you (and many others) use. BlitzPlus contains this same 2D command set plus some GUI stuff, but no 3D commands. Rhy :) |
| ||
| Hi Rhy, Framerates will drop using WPF with multiple shadows and larger areas plus I want softshadows which would involve a bit more math using a fill routine. I'll check whether I can do what I want with SpriteCandy or NSpritePro. I'll be using those for the lightblend and shadeblend required anyway. Thanks for your help |
| ||
| Have you checked out Swifts shadow system? http://www.blitzbasic.com/toolbox/toolbox.php?tool=87 |
| ||
| Yes I have. Thanks for the suggestion |