How can I capture world...

Blitz3D Forums/Blitz3D Beginners Area/How can I capture world...

hollifd(Posted 2008) [#1]
I need to figure out a way to capture all of the objects' locations and save to a file.

I am working on a machine simulator for bending sheet metal parts. I am thinking that I want the user to be able to set the machine settings for each bend on the sheet metal part and then click a button to save the settings. The sheet metal part can have many bends, so I need to be able to save many machine settings.

For example:
Image a box without a lid. It will have 5 sides...a left, right, back, front and bottom. To make a sheet metal box like that it will start off flat and look similar to a cross. If you fold up each of the 4 legs of the cross, you will end up with a 5 sided box.

So I have a "machine" programmed in Blitz that allows the user to import a flat sheet metal part from a CAD system. The user can move the flat part on the screen and also move parts of the machine around until the part and machine "fit" like the user wants. Once the machine setup is correct, I want the user to be able to click on a button that will "save" all of these positions...the part positions and machine positions. For each bend on the part, I will need to be able to save the part and machine positions.

Ultimately, I want to be able to recall these part and machine positions and play them back on the screen and maybe even change the order of the playback.

I feel confident that I can write a file to save this information but I need help with how to "Capture all of the positions so that I can write them to the file.

So...Is it easy to capture all of the positions of my entities (X, Y, Z, angles etc)? If so, can you give me a hint of how it can be done?

Thanks,

David


Ross C(Posted 2008) [#2]
You need to keep track of the entities, in either an array, or a type list. You can't really do this, without the above.

Then, it's just a case of looping through each entity and calling EntityX(), EntityY() and EntityZ(), and EntityPitch(), EntityYaw() and EntityRoll().


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

You always seem to be here (there?) to answer my questions. Thanks for that.

If I understand correctly...

If I have 4 entities like Gage1, Gage2, Part1 and Part2, I can code something like:

Open "C:\Temp\capture.txt" for output as #1
Print #1,  EntityX(Gage1) & "," &  EntityY(Gage1) & "," & EntityZ(Gage1) & "," & EntityPitch(Gage1) & "," & EntityYaw(Gage1) & "," & EntityRoll(Gage1)

Print #1,  EntityX(Gage2) & "," &  EntityY(Gage2) & "," & EntityZ(Gage2) & "," &  EntityPitch(Gage2) & "," & EntityYaw(Gage2) & "," & EntityRoll(Gage2)

Print #1,  EntityX(Part1) & "," & EntityY(Part1) & "," &  EntityZ(Part1) & "," &  EntityPitch(Part1) & "," &  EntityYaw(Part1) & "," &  EntityRoll(Part1)

Print #1,  EntityX(Part2) & "," &  EntityY(Part2) & "," &  EntityZ(Part2) & "," &  EntityPitch(Part2) & "," &  EntityYaw(Part2) & "," &  EntityRoll(Part2)

Close #1



Then, when I am ready to reset all of my entities back to a previously saved state, just read that data back in and use commands like: PositionEntity and RotateEntity


I know the open file syntax above is not Blitz. I will have to adjust that when the time comes.

Is there some other easy way to loop through all of my entities? Right now, I think that I only need locations for 4 entities but for future reference, is there a easy way?

Thanks,

David


KillerX(Posted 2008) [#4]
; Reading and writing custom types to files using ReadFile, WriteFile and CloseFile

; Initialise some variables for the example
Type HighScore
Field Name$
Field Score%
Field Level%
End Type

Best.HighScore = New HighScore
Best\Name = "Mark"
Best\Score = 11657
Best\Level = 34

; Open a file to write to
fileout = WriteFile("mydata.dat")

; Write the information to the file
WriteString( fileout, Best\Name )
WriteInt( fileout, Best\Score )
WriteByte( fileout, Best\Level )

; Close the file
CloseFile( fileout )

; Open the file to Read
filein = ReadFile("mydata.dat")

; Lets read the Greatest score from the file
Greatest.HighScore = New HighScore
Greatest\Name$ = ReadString$( filein )
Greatest\Score = ReadInt( filein )
Greatest\Level = ReadByte( filein )

; Close the file once reading is finished
CloseFile( fileout )

Print "High score record read from - mydata.dat "
Print
Write "Name = "
Print Greatest\Name
Write "Score = "
Print Greatest\Score
Write "Level = "
Print Greatest\Level

WaitKey()


This is an example from the manual.


Ross C(Posted 2008) [#5]
You'll need to use either arrays or type objects.

Type Machine_Part
   Field name$
   Field entity
End Type


m.machine_part = new machine_part

m\name$ = "Gage1"
m\entity = createsphere() ; just for example

m\name$ = "Gage2"
m\entity = createsphere() ; just for example

m\name$ = "Part1"
m\entity = createsphere() ; just for example

m\name$ = "Part2"
m\entity = createsphere() ; just for example

Open "C:\Temp\capture.txt" for output as #1

For m.machine_part = Each machine_part

   Print #1,EntityX(m\entity)& "," & EntityY(m\entity) & "," & EntityZ(m\entity)

Next



That will loop through every entity you have created in that type and save them to the text file. Obviously not the correct syntax used, but you get my drift :o)


hollifd(Posted 2008) [#6]
Thanks Joseph,

That will be helpful.

David


hollifd(Posted 2008) [#7]
Thanks Ross C.

That will keep me busy for a while.

David


Zethrax(Posted 2008) [#8]
Another way to parse your entities would be to create a pivot and parent all your top level (normally unparented) entities to that. You could then simply recurse the child lists originating with that pivot.

Eg.

Graphics 800, 600, 0, 2
SetBuffer BackBuffer()

Global G_world = CreatePivot()

; Example entities.
CreateSphere( CreateSphere( G_world ) )



Function RecurseAllEntities( entity )

; Perform whatever operation you need to regarding 'entity' here.

Local num, i

num = CountChildren( entity )

For i = 1 To num

	RecurseAllEntities( GetChild ( entity, i ) )
	
Next

End Function


RecurseAllEntities( G_world )

End




hollifd(Posted 2008) [#9]
Thank you Bill.

I see how that works. I will keep that method in my back pocket for later use.

David


hollifd(Posted 2008) [#10]
Am I missing something with writing files?

I can't seem to find how to append data to a plain text file.

In VB, you can use something like:
Open "C:\Temp\junk.txt" for append as #1
Print #1, "Some text"
close #1


I cannot seem to find out how to open a file in Blitz for append. I want to work with a plain text file. Is this possible?

Here is the code that I am currently working with...
fileout=writefile("C:\Temp\junk.txt")
writeline(fileout, "Some Text")
closefile(fileout)


If Blitz does not have any built-in methods to append data to a plain text file, then I can do it other ways but I was hoping for a simple solution.

Thanks for any help,

David


KillerX(Posted 2008) [#11]
That code saves it as a plain text file for me. Jusy make sure that the path is valid. I had to change the path for it to work.


hollifd(Posted 2008) [#12]
KillerX,

I meant that I need to write to that file on more than one occassion. For example: I want the user to click a button and data will get written to that file. Later on, I want the user to click a button again and have more information written to that same file. I do not see where I can reopen an existing file to append data to the file. I can figure out other ways to do it but I was hoping for a built-in easy solution to append plain text data to an existing file.

Thanks,

David


Ross C(Posted 2008) [#13]
I believe you have to write the whole file again. You can insert data i'm sure though, but it's a bit trickier.


hollifd(Posted 2008) [#14]
OK.

I thought maybe I just missed something in the help file that allows appending data to a plain text file.

I will have to get more creative then.

I can allow the user to click a button and save data to text files that get named by my code and when I need all of the data to be in one file, I can just read the directory for all of the text files that were created and copy the contents of each file into my one big combined file and then delete all of the individual files. Maybe I will think of some better solution later but that should work for me for now.

Thanks,

David


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

By the way, with your help, I am now able to save all of my entities positions to a text file as many times as I want and then read those files back in to review the positions that were saved. It works very good.

Thanks,

David


Warner(Posted 2008) [#16]
Doesn't OpenFile work for appending data to files ?


hollifd(Posted 2008) [#17]
I saw that in the help but it talked about using FilePos and SeekFile but the files will be of unknown length and I was not sure how to find the end of the file.

However, it just occured to me that I can use OpenFile and use some code like this to read the entire file before writing any new stuff to it...

;Create a new text file and write some text to it
FileOut=WriteFile("C:\Temp\Junk.txt")
     WriteLine(FileOut, "Line1")
CloseFile(FileOut)

;Open an existing text file, read to the end of it and then write more text to it
FileOut=OpenFile("C:\Temp\Junk.txt")
While Not EOF(FileOut)
     Hold$ = ReadLine(FileOut)
Wend

;Now that we are at the end of the file, let's write some new text to it
WriteLine(FileOut, "More text.")

;Close the file now
CloseFile(FileOut)



So, this should work for me. If there is an easier way, please let me know.

Thanks for the tip.

David


Ross C(Posted 2008) [#18]
Easiest is just saving over the top of the file tbh. Basically rewriting everything. Since you will probably have a save file function anyway, it should be easy :o)


Kev(Posted 2008) [#19]
use filesize() to get the end of the file. NOTE when using OpenFile() the file has to exists. you could use WriteFile() to create the file then use OpenFile() to append to it

filename$ = "test.txt"
file = OpenFile(filename$)
SeekFile(file,FileSize(filename$))
WriteLine(file,"hello")
CloseFile(file)



hollifd(Posted 2008) [#20]
Thanks Kev. Thanks looks simpler and probably faster too.

Ross C,

My issue is that I allow the user to move things on the screen and when everything is where the user wants it, he can press a save button and all of the entities locations will get saved. But most of the time, the user will need to move the stuff on the screen again and will need to save the new locations in addition to the previously saved locations. The user will need to do this multiple times, sometimes as many as 25 times.

Finally, after moving things around on the screen and saving the locations, the user will need to push a button and play back each of the saved locations to verify that he located everything properly.

Sometimes, it will be necessary for the user to change the order of the saved locations too. For example, if the user moves things on the screen and saves the locations, they get saved as Step1. Then the user might need to move the stuff on the screen again and save the new locations as Step2. After clicking a button to play back the 2 steps, the user might choose to swap the order of the steps so that Step2 is before Step1.

I know this is probably very confusing to you since you do not know exactly what I am trying to do with this program.

I suppose that I could write all of this stuff to an array rather than a file. I just chose a file since I am much more familiar with working with files than arrays.

Thanks,

David


Kev(Posted 2008) [#21]
use types this way you have full control of the saved locations, should a user wish to move a save position then you could simply modify the order of the types list. hence should the user wish to save new position add them to the type list.


hollifd(Posted 2008) [#22]
Kev,

I am not sure that I understand what you mean as I am just learning to use Types thanks to Ross C. Do you have some simple code for me to look at?

Example:
1. display a simple single cube.
2. allow the user to move it then press a button to save the location
3. allow the user to move it again then press a button to save the location again
4. press a button to play back the two saved locations with a waitkey in between steps

This is what I think you mean...
Type Positions
     Field StepNumber
     Field EntityNumber
     Field XPos
     Field YPos
     Field ZPos
     Field Pitch
     Field Yaw
     Field Roll
End Type


Then when the user wants to save a step, add to the list. Then give some way to reorder the list and maybe even delete steps from the list?


Thanks,

David


Kev(Posted 2008) [#23]
hollifd, heres a very basic example and not put together well, what it does is take the position of the cube and store it in the type each time space is pressed. pressing f1 and then the mousebutton will loop through the positions in the type

;
;
;

Type Tobject
	
		Field ob_id	
		Field entity
		Field x#,y#,z#
		Field pitch#,Yaw#,roll#

End Type

Graphics3D 640,480,16,2
SetBuffer BackBuffer()

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

cube = CreateCube()
PositionEntity cube,0,0,15

While Not KeyDown(1)
	
	If KeyHit(59) Then

		For o.Tobject = Each Tobject
			PositionEntity o\entity,o\x#,o\y#,o\z#
					
			UpdateWorld
			RenderWorld
			
			Text 100,100,"press mouse button for next position"
			MouseWait
			Flip
		Next
	EndIf
	
	If KeyHit(57) Then
		o.Tobject = New Tobject
		o\entity = cube ; this could be the selected entity
		o\x# = EntityX(o\entity)
		o\y# = EntityY(o\entity)
		o\z# = EntityZ(o\entity)
	EndIf
	
	If KeyDown(203)
		MoveEntity cube,-.3,0,0
	EndIf

	If KeyDown(205)
		MoveEntity cube,.3,0,0
	EndIf
	
	UpdateWorld
	RenderWorld
	
	Text 10,10,"space to snap position"
	Text 10,30,"f1 to play positions"
	
	Flip
	
Wend
End


this code will add ten items to a type list and then loop though and if the index of the type = 6 a new type is inserted before and after number 6, to show this ive marked the new entrys as -1

;
;
;

Type Tobject
	
		Field ob_id	
		Field entity
		Field x#,y#,z#
		Field pitch#,Yaw#,roll#

End Type

For add_item = 0 To 10
	o.Tobject = New Tobject
	o\ob_id	= add_item
Next


; this loops through until the type\ob_id=6, we then insert one item before and mark is as -1
For o.Tobject = Each Tobject
	If o\ob_id = 6 Then
		insert_o.Tobject = New Tobject
		insert_o\ob_id = -1
		Insert insert_o Before  o
	EndIf
Next

; this loops through until the type\ob_id=6, we then insert one item after and mark is as -1
For o.Tobject = Each Tobject
	If o\ob_id = 6 Then
		insert_o.Tobject = New Tobject
		insert_o\ob_id = -1
		Insert insert_o After o
	EndIf
Next

; standard loop of types in the Tobject list 
For o.Tobject = Each Tobject
	Print o\ob_id	
Next
 
MouseWait
End


both example's are basic but will point you in the right direction, i hope.


hollifd(Posted 2008) [#24]
Kev,

Now I understand better what you are doing. I am having family in this weekend but I want to study this more early next week to get a better grip on Types as I am sure this is the way to go and will make life much easier and my coding much better. I have coded some of this already without using Types and the code is very messy and very long.

Thanks again,

David