How can I zoom...

Blitz3D Forums/Blitz3D Beginners Area/How can I zoom...

hollifd(Posted 2008) [#1]
I want to create a top down view of a machine where the user can import a 2D CAD DXF file of a sheet metal part and then be able to move the machine and part and get various pieces of data. I have alot of it working but have realized that I need some zooming capabilities because the machine is very large and sometimes the parts are very small and I need to be able to zoom in on the small parts so that I can see them better. How can I zoom?

Here is a sample of my code so far that does not have any zooming capabilities. You use the arrow keys to move the machine parts around.

Thanks for any help,

David



Graphics3D 1280, 960
SetBuffer BackBuffer()
AppTitle "Autoform Gage Simulation"

CenterX = GraphicsWidth()/2
CenterY = GraphicsHeight()/2
MyScale = 10

LBoxX# = CenterX - 10 * MyScale
LBoxY# = CenterY - 100
RBoxX# = CenterX + 9 * MyScale
RBoxY# = CenterY - 100
FingerToMove$ = "BOTH"
XMovementAmount = 1
YMovementAmount = 1



ClsColor 255,255,255
Cls

While Not KeyDown(1)
Color 0,0,0
If KeyDown(203) Then ;move left
If FingerToMove = "LEFT ONLY" Then
LBoxX = LBoxX - XMovementAmount
End If
If FingerToMove = "RIGHT ONLY" Then
RBoxX = RBoxX - XMovementAmount
End If
If FingerToMove = "BOTH" Then
LBoxX = LBoxX - XMovementAmount
RBoxX = RBoxX - XMovementAmount
End If
If FingerToMove = "PART" Then
PartX# = PartX# - XMovementAmount
End If
End If

If KeyDown(205) Then ;move right
If FingerToMove = "LEFT ONLY" Then
LBoxX = LBoxX + XMovementAmount
End If
If FingerToMove = "RIGHT ONLY" Then
RBoxX = RBoxX + XMovementAmount
End If
If FingerToMove = "BOTH" Then
LBoxX = LBoxX + XMovementAmount
RBoxX = RBoxX + XMovementAmount
End If
If FingerToMove = "PART" Then
PartX# = PartX# + XMovementAmount
End If
End If

If KeyDown(200) Then ;move up
If FingerToMove = "LEFT ONLY" Then
LBoxY = LBoxY - YMovementAmount
End If
If FingerToMove = "RIGHT ONLY" Then
RBoxY = RBoxY - YMovementAmount
End If
If FingerToMove = "BOTH" Then
LBoxY = LBoxY - YMovementAmount
RBoxY = RBoxY - YMovementAmount
End If
If FingerToMove = "PART" Then
PartY# = PartY# - YMovementAmount
End If
End If

If KeyDown(208) Then ;move down
If FingerToMove = "LEFT ONLY" Then
LBoxY = LBoxY + YMovementAmount
End If
If FingerToMove = "RIGHT ONLY" Then
RBoxY = RBoxY + YMovementAmount
End If
If FingerToMove = "BOTH" Then
LBoxY = LBoxY + YMovementAmount
RBoxY = RBoxY + YMovementAmount
End If
If FingerToMove = "PART" Then
PartY# = PartY# + YMovementAmount
End If
End If

If KeyHit(29) Then ;toggle which finger(s) to move
Select FingerToMove
Case "PART"
FingerToMove = "LEFT ONLY"

Case "LEFT ONLY"
FingerToMove = "RIGHT ONLY"

Case "RIGHT ONLY"
FingerToMove = "BOTH"

Case "BOTH"
FingerToMove = "PART"
End Select
End If


;draw left gauge now...
Rect(LBoxX, LBoxY, 1 * MyScale, 1.5 * MyScale,0)
Line(LBoxX + 1 * MyScale, LBoxY + .5 * MyScale, LBoxX + 2 * MyScale, LBoxY + .5 * MyScale)
Line(LBoxX + 2 * MyScale, LBoxY + .5 * MyScale, LBoxX + 2 * MyScale, LBoxY + 2.5 * MyScale)
Line(LBoxX + 2 * MyScale, LBoxY + 2.5 * MyScale, LBoxX + 1.75 * MyScale, LBoxY + 2.5 * MyScale)
Line(LBoxX + 1.75 * MyScale, LBoxY + 2.5 * MyScale, LBoxX + 1.75 * MyScale, LBoxY + 2.375 * MyScale)
Line(LBoxX + 1.75 * MyScale, LBoxY + 2.375 * MyScale, LBoxX, LBoxY + 1.5 * MyScale)

;Line(CenterX - 60 * MyScale, LBoxY - 15, LBoxX + .5 * MyScale, LBoxY - 15)
;Text CenterX - 63 * MyScale + ((LBoxX + .5 * MyScale) - (CenterX - 60 * MyScale))/2, LBoxY - 15, Str$(LBoxX / MyScale - 63.5)



;draw right gauge now...
Rect(RBoxX, RBoxY, 1 * MyScale, 1.5 * MyScale,0)
Line(RBoxX, RBoxY + .5 * MyScale, RBoxX - 1 * MyScale, RBoxY + .5 * MyScale)
Line(RBoxX - 1 * MyScale, RBoxY + .5 * MyScale, RBoxX - 1 * MyScale, RBoxY + 2.5 * MyScale)
Line(RBoxX - 1 * MyScale, RBoxY + 2.5 * MyScale, RBoxX - .75 * MyScale, RBoxY +2.5 * MyScale)
Line(RBoxX - .75 * MyScale, RBoxY + 2.5 * MyScale, RBoxX - .75 * MyScale, RBoxY + 2.375 * MyScale)
Line(RBoxX - .75 * MyScale, RBoxY + 2.375 * MyScale, RBoxX + 1 * MyScale, RBoxY + 1.5 * MyScale)

;Line(CenterX + 60 * MyScale, RBoxY - 15, RBoxX + .5 * MyScale, RBoxY - 15)
;Text CenterX + 63 * MyScale + ((RBoxX - .5 * MyScale) - (CenterX + 60 * MyScale))/2, RBoxY - 15, Str$(RBoxX / MyScale - 63.5)


;draw bed centerline
Line(CenterX, CenterY, CenterX, CenterY + 2.5 * MyScale)

;draw bed
Line(CenterX, CenterY, CenterX + 60 * MyScale, CenterY)
Line(CenterX, CenterY, CenterX - 60 * MyScale, CenterY)
Line(CenterX, CenterY + 2.5 * MyScale, CenterX + 60 * MyScale, CenterY + 2.5 * MyScale)
Line(CenterX, CenterY + 2.5 * MyScale, CenterX - 60 * MyScale, CenterY + 2.5 * MyScale)

;draw tooling centerline now...
Color 255,0,0
Line(CenterX - 60 * MyScale, CenterY + 1.25 * MyScale, CenterX + 60 * MyScale, CenterY + 1.25 * MyScale)

;draw maximum X axis location now
Line(CenterX - 60 * MyScale, CenterY - 22.75 * MyScale, CenterX + 60 * MyScale, CenterY - 22.75 * MyScale)



Color 0,0,0

If ReadPixel(LBoxX,LBoxY + 2.5 * MyScale) = -65536 Then
Collision = 1
End If

If ReadPixel(RBoxX,RBoxY + 2.5 * MyScale) = -65536 Then
Collision = 2
End If

Select Collision
Case 0
;print the gage locations to the screen
Text 10, 10, "ZLeft = " + Str$(LBoxX / MyScale - 63.5)
Text 160, 10, "ZRight = " + Str$(RBoxX / MyScale - 63.5)
Text 10, 25, "XLeft = " + Str$((LBoxY / MyScale - 46.75)*-1)
Text 160, 25,"XRight = " + Str$((RBoxY / MyScale - 46.75)*-1)
Text 10, 40, "Finger to move LFT CTRL KEY = " + FingerToMove
Text 10, 55, "OK"

Case 1
While Not KeyDown(46)
;print the gage locations to the screen
Text 10, 10, "ZLeft = " + Str$(LBoxX / MyScale - 63.5)
Text 160, 10, "ZRight = " + Str$(RBoxX / MyScale - 63.5)
If (LBoxY / MyScale - 46.75)*-1 > 1.25 Then
Text 10, 25, "XLeft = " + "24.000"
Else
Text 10, 25, "XLeft = " + "0.000"
End If
Text 160, 25,"XRight = " + Str$((RBoxY / MyScale - 46.75) * -1)
Text 10, 40, "Finger to move LFT CTRL KEY = " + FingerToMove
Text 10, 55, "Left Gage Collision Detected !!! Press C and a direction button to continue."
Flip
Wend
Collision = 0

Case 2
While Not KeyDown(46)
;print the gage locations to the screen
Text 10, 10, "ZLeft = " + Str$(LBoxX / MyScale - 63.5)
Text 160, 10, "ZRight = " + Str$(RBoxX / MyScale - 63.5)
Text 10, 25, "XLeft = " + Str$((LBoxY / MyScale - 46.75)*-1)
If (RBoxY / MyScale - 46.75)*-1 > 1.25 Then
Text 160, 25, "XRight = " + "24.000"
Else
Text 160, 25, "XRight = " + "0.000"
End If
Text 10, 40, "Finger to move LFT CTRL KEY = " + FingerToMove
Text 10, 55, "Right Gage Collision !!! Press C and a direction button to continue."
Flip
Wend
Collision = 0
End Select

Flip

Cls

Wend
End


D4NM4N(Posted 2008) [#2]
- edit - Post deleted. Ah, nevermind, ive just seen its all in 2d. sorry. (im at work & didnt read it carefully enough :P)

-edit 2-
Heres an idea though:

Let 3D help :
You should be able to recreate it in 3D space (just dont use the Z axis) using a system of dynamic invisible pivots (see createpivot & freeentity) that are deleted/created when they and/or their linked counterparts are on/off screen respectively, using a custom data type (or array) that stores the coords of the 2 pivots that make it up (or use 4 for rectangles).
Then use the line command to join up the screen coords of those pivots (see cameraproject command).
Lastly use b3d's orthomode (cameraprojmode cam,2) with the camerazoom command. Redrawing the lines after the zoom.

Worth a try and would save you a lot of maths design. You could even create a way of editing the points easily too if you wanted to do that.

Im sure someone will have a nice 2d solution for you if you hold out though :)


hollifd(Posted 2008) [#3]
Thanks for the idea but I am a beginner and will hold out to see if someone might offer a simpler solution as I did not understand all of your ideas.

I have thought about 3D but I could not figure out how to import my 2D DXF CAD file into a 3D environment. The 2D DXF CAD file has information required for drawing lines, circles and partial circles (arcs). I could not figure out how take those 2D elements and draw them into a 3D part. If I could figure that out, 3D would be a much better solution for me because it would provide a way for me to flip, rotate and move the part around on the screen much easier.

Still looking for a simple zoom solution, if there is such a thing.

Thanks,

David


Gabriel(Posted 2008) [#4]
Why not just do all your 2d drawing, copy the screen to a texture and then display the texture on a quad?


hollifd(Posted 2008) [#5]
Gabriel,

I am so new that I don't even know what a quad is. It might work but I would need to learn about what a quad is.

I need to be able to interactively move my machine parts and the flat sheet metal part around on the screen and be able to zoom in and out to see better. As I move the machine parts around on the screen, I need the X-Left, X-Right, Z-Left and Z-Right locations to update appropriately and accurately.

The X-Left, Z-Left etc. are parts of a machine that are used for positioning flat sheet metal parts so that they can be bent into a 3D shape.

Does this still sound like your idea might work?

Thanks,

David


Gabriel(Posted 2008) [#6]
A quad is just a completely flat 3d rectangular object. It's 3d in theory because it has a three dimensional position, but in practice, it's just a 2D item you can scale.

You can interactively do whatever you want to do because you're still going to be drawing it every frame, just as you are in 2d. The only difference is that - because it's a 3d element - you'll be able to scale it any size you want, which equates to zooming in or out.


KillerX(Posted 2008) [#7]
You can also zoom into a quad with CameraZoom


Ross C(Posted 2008) [#8]
I have limited experience with CAD, i did it for a few years. From what i can remember, The CAD zoom is very much the same as a vector drawing program zoom. There should be no blocky lines or graphics, no matter how many times you can zoom in.

Why not set a size for your screen.

Say 5000 x 5000 units. Now, you will have a screen_start_x variable, and a screen_start_y variable, and obviously a screenwidth and screenheight.

Now, instead of saying a line stretches from (0,0) to (1280,0) across the full length of your screen, based on your choosen resolution, you would say the lines co-ordinates are (0,0) to (5000,0).

Now, when it comes to drawing you will need to translate these unit co-ords to actual onscreen co-ords. For example:

Unit co-ords of a line (0,0) (5000,0)

Now since 5000 is your maximum screen unit width, and 1280 is your maximum screen pixel width, you will need to clip the line at each end of the screen, and based on where the viewport is. Blitz will clip the graphics for you.

Graphics 800,600
SetBuffer BackBuffer()




While Not KeyHit(1)

	Cls

	Oval -1000,0,1050,300
	
	Flip
	
Wend


That draws an oval, starting from -1000, and stretching 1050 across and 300 down. Only 50 pixels across are showing. The only problem is slight inaccuracies you'd get, only a pixel out at any one time. The fact a unit may lie between two pixels at a zoomed out factor.


hollifd(Posted 2008) [#9]
Guys...

Thanks for all of the information. I am at work now but I will try some of these ideas out when I get home and see if I can get something to work.

Thanks again,

David


Stevie G(Posted 2008) [#10]
Not sure about the format of DXF files but if it is basically a list of points and lines then it should be easy to implement a 2d zoom.

For example.

NOTE: this is just typed straight into the thread so won't work off the bat. I'm also assuming that your just reading the points / lines from data statements which will not be the case. I'm also pretty sure that you can re-define arrays like this but I may be wrong.

global Lines
global Points

;array to store point x & y coords
dim PointX#(0)
dim PointY#(0)
;array to store zoomed x & y coords
dim PointZX#(0)
dim PointZY#(0)
;array to store line start and end point indices.
dim LineS(0)
dim LineE(0)

INIT()
DRAW()
mousewait
end

;=====================================
;=====================================
;=====================================

;read all the points / lines
Function INIT()

Restore MyData
read Points
dim PointX#( Points - 1 )
dim PointY#( Points - 1 )
dim PointZX#( Points - 1 )
dim PointZY#( Points - 1 )

read Lines
dim LineS( Lines - 1 )
dim LineE( Lines - 1 )

;read all point x & y coords
for p = 0 to Points - 1
  read PointX( p )
  read PointY( p )
next

;read all start and end point indexes
for l = 0 to Lines - 1
  read LineS( l )
  read LineE( l )
next

end function

;=====================================
;=====================================
;=====================================

function DRAW( Ox# , Oy# , Zoom# = 1.0 )

  ;get new point coords after applying zoom on origin Ox, Oy
  for p = 0 to Points - 1
    PointZX( p ) = ( PointX( p ) - Ox ) * Zoom
    PointZY( p ) = ( PointY( p ) - Oy ) * Zoom
  next

  ;draw the lines for the new points
  for l = 0 to Lines - 1
      Line PointZX( LineS( l ) ) , PointZY( LineS( l ) ) , PointZX( LineF( l ) ) , PointZY( LineF( l ) )
  next

end function

;=====================================
;=====================================
;=====================================



Ross C(Posted 2008) [#11]
Ok man, i've completed my little code. Can't nail the little zoom problem i'm having though... Floating point inaccuracy somewhere i thinks. Anyway:



Using something like stevie has posted to make the lines. I've only hardcoded in an oval to demonstrate real time zooming and movement.

Arrow keys to move. PageUP and PageDOWN to zoom in and out. The comments for the zooming code is inaccurate, as i changed it :oS


hollifd(Posted 2008) [#12]
Ross C,

That is an impressive piece of code. I will give it a try and see if it will work for me.

Thanks for your time and help with this.

David


Ross C(Posted 2008) [#13]
All you really need to do plot your points or draw your lines, using the unit scale and not the pixel scale. For instance if your line goes from 100 to 500, and the number of units on the screen is 1600,1200, the line would go from:

max_unit_x# = 1600 ; the number of units across your screen.
max_pixels_x# = 800 ; the number of pixels wide your screen is
ratio = max_pixels / max_unit_x

Multiply ever co-ord for your line/oval/plot, by the ratio figure. The drawviewport code will translate your unit co-ords back to pixel co-ords onscreen when drawing.

And your very welcome :o)


puki(Posted 2008) [#14]
"hollifd" your User ID is 2195. Did you buy Blitz a few years back then stopped using it?


hollifd(Posted 2008) [#15]
puki,

I bought it from someone on Ebay (maybe a year or two ago?) and have not used it (mostly because I don't know how). I am fascinated at some of the things I have seen users create and am just now trying to learn more about it. I work as a manufacturing engineer and am trying to create a machine simulator with some CAD type functionality using Blitz and am struggling a bit.

I think it would be easier if I could do some of this in 3D but have not been able to figure out how to create lines, circles and arcs in 3D. I need to work with 2D DXF CAD files and write some code that will read through the DXF file to get the information for each line, circle and arc. I think I have figured out the DXF file format but have not figured out how to draw the lines, circles and arcs to create a 3D part.

Here is what I THINK I need to do...
I think I need to read the DXF file and get the information for all of the lines, circles and arcs then draw them onto the screen. Then I think I need to WELD them all together so that they will all move, flip and rotate together?

At some point, I will probably ask some more questions on this board to see if anyone can help.

David


Ross C(Posted 2008) [#16]
Tbh, i think 2d might be easier for you, especially if your new. You don't need to worry about surfaces, cameras, vertex co-ords, creating quads.

Althought zooming is far easier, what i have given you above, is more than enough for doing the zooming stuff.

With 2d, you just need to draw your arcs and lines everyframe and not worry about clipping issues, drawing too many quads etc.


hollifd(Posted 2008) [#17]
Ross C,

Anonther reason that I think 3D might be easier is because I also need the ability to flip my part over and rotate it. I guess through code I could rotate all of the X and Y coordinates of each line and arc around a center point in order to rotate the part. As far as flipping the part, I will need to see what needs to happen to each of the X and Y coordinates in order to create the flip.

I have thought about just drawing the part on the screen and then create an image from the drawing, then use some of the built in commands for rotating and flipping the image. I am not sure what will happen when I try to zoom in and out with this method. My guess is that everything except the image will zoom in and out.

I want to experiment with one of the ideas above about drawing to a texture and then placing the texture onto a cube (quad?) just to see what that might do for me.

I want to also look at our CAD software and see if it can export a file format that is able to be imported into Blitz3D. That seems like it would make things alot simpler too.

Anyway...I am having fun (?) with this and learning a few tricks too.

David


Ross C(Posted 2008) [#18]
Flipping would be very easy, and so would rotating, if it's just rotating points that make up shapes.

Make a centre point, then use SIN and COS to find your new points.

If you zoom into an image, it will just appear as it does i'm afraid. Zooming into a bitmap will produce a blocky effect, but there is no reason why you need to change your part into an image.

If you want to learn more about programming, try the 2d way first. When you go into 3d, trying to draw an arc, with a series of joined up quads is possible, BUT, when you zoom in, which will be a breeze, your lines will get thicker, unless your dynamically alter all the quads.

So, either way, you will have problems to overcome, that the other option won't have. Since you have a working zoom code, that seems to be most of the troubles of the 2d finished.

A note about zooming into the texture on a cube as you suggested. If you drew some lines in paint, them zoomed into them, you'd get a blocky version of what you have drawn. Same applies in 3d, unless you vectorise the 3d drawing, in which case, drawing to a texture would be kind of out the window :o)

Try drawing a small CAD drawing saving it as a square texture 2x2 or 4x4 or 8x8 or 16x16... etc, must be multiple of 2. Texture a cube with it, and place the camera at different distances away, to quickly see the effect of what will happen :o)

Glad your having fun with this too :o)

Good luck!


hollifd(Posted 2008) [#19]
Ross C,

I tried drawing to a texture and it does not seem all that bad. The zooming is very easy but I can see what you mean about the lines not remaining crystal clear. I don't think it will be a problem for what I am trying to do.

One problem that I do not understand...
If I want to use this method, how do I size the texture to fit exactly onto my cube. It looks like the texture is being stretched to fit onto the cube and the graphics are being distorted. Is there a way that I can draw to a texture size and when I apply the texture to the cube it will be placed onto the cube without and distortion of my lines and arcs. Hopefully you can uderstand what I am trying to say.

Here is the code that I used...
Use the arrow keys to move the camera
Use Z to zoom in
User V to zoom out



Graphics3D 640,480
SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera, 0,0,-250


light=CreateLight()
RotateEntity light,90,0,0

cube=CreateCube()
PositionEntity cube,0,0,0
ScaleEntity cube, 120,120,1


; Create texture of size 256x256
tex=CreateTexture( 640,480 )

; Set buffer - texture buffer
SetBuffer TextureBuffer( tex )

; Clear texture buffer with background white color
ClsColor 255,255,255
Cls

; Draw some sample lines / circles on the screen
Color 0,0,0
Rect(10, 10, 630, 470, 0)
Oval(270, 190, 100, 100, 0)

; Texture cube with texture
EntityTexture cube,tex

; Set buffer - backbuffer
SetBuffer BackBuffer()

While Not KeyDown( 1 )

If KeyDown( 208 ) Then
MoveEntity camera, 0,-1,0
End If
If KeyDown( 200 ) Then
MoveEntity camera, 0,1,0
End If
If KeyDown( 203 ) Then
MoveEntity camera, -1,0,0
End If
If KeyDown( 205 ) Then
MoveEntity camera, 1,0,0
End If
If KeyDown( 44 ) Then
MoveEntity camera, 0,0,1
End If
If KeyDown( 47 ) Then
MoveEntity camera, 0,0,-1
End If

RenderWorld
Flip

Wend

End


Stevie G(Posted 2008) [#20]
tex=CreateTexture( 640,480 ) 


This will create a texture of 1024 x 512 on most cards as they'll round to the nearest power of 2. Obviously this is non-square so will look distorted on a cube. If you create a texture of 1024 x 1024 it should look fine.

Alteratively you can use scaletexture to adjust the uv's.

Stevie


hollifd(Posted 2008) [#21]
Thanks Stevie G.

When I create the texture at 1024 x 1024, my picture does not look distorted any more.


Is there a way to take my simple rectangle and hole drawing and create a 3D model? The model can be flat or have thickness and should be wireframe so that I can see through it.

Ultimately, I want to read a 2D DXF CAD file draw lines, circles and partial circles. I have seen some code here about drawing 3D lines and I am wondering if I might be able to utilize that to draw a part in 3D. For the circles, maybe I could use very short line segments rotated around an axis to simulate the look of a circle.

Thanks,

David




David