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 |