Getting the viewport dimensions

I'm using breve's image class to store "blended" pictures of the best individuals in each generation (my simulation is based on the "Walker" demo included with breve). Here is an example pic:
http://www.jignacio.com.ar/cosas/bestrobot_gen_5~picture.png

Is there a way to get the current size of the viewport? Right now I'm using fixed 400x400 pixel images, but ideally I would like to capture the full viewport, at its current resolution.

Also, and this is purely cosmetic, is there a way to set the scale of a texture differently for each axis?
My simulated robots have a variable number of legs, so being able to change the scale of the texture used in the body on one axis (the length of the body) while leaving the other constant (the width) would be very useful.

Thanks in advance!

Ignacio

Re: Getting the viewport dimensions

Looks very interesting! How are you doing the blending?

PowerMacX wrote:Is there a way to get the current size of the viewport? Right now I'm using fixed 400x400 pixel images, but ideally I would like to capture the full viewport, at its current resolution.

I've added this for the next version. The Camera class now has methods get-width and get-height which will return this information.

PowerMacX wrote:Also, and this is purely cosmetic, is there a way to set the scale of a texture differently for each axis?

I've added this too. The Real class will now have methods set-texture-scale-x and set-texture-scale-y to handle the texture scales independently.

- jon

Re: Getting the viewport dimensions

jk wrote:Looks very interesting! How are you doing the blending?

Basically, the process is relatively slow, so I don't blend the images of every robot, only those from the best robot in each generation.

To do this, I take one snapshot every n seconds (the TIME_BETWEEN_SNAPSHOTS constant), and store it in a list of images. This is pretty fast, and doesn't have any noticeable effect on the simulation performance.

There are two list of images (historyImage[0] & [1]), so after I fill the first list with the pictures of first robot walk and the second list with the pictures of the second, I keep track of the associated fitness of each.

Then, the next robots' pictures are saved to the image list with the lowest fitness of the two, overwriting it, since I only care about keeping the pictures of the best. This way I don't have to keep an image array for each robot in a generation and therefore this uses a lot less memory.

Here is the specific code that does the above:

+ variables:
	baseImage (object).
	finalImage (object).
	historyImage (2 lists).
	x,y (int).
	pixelColor,newPixelColor (vector).
	numHistoryImages (int).
	currentHistoryImageList (list).
	currentHistoryImageListIndex (int).
	currentHistoryImageIndex (int).
	...
	

+ to init:
	...
	baseImage = new Image.
	finalImage = new Image.
	number = ((currentSimulationConfig get-simulation-time)/TIME_BETWEEN_SNAPSHOTS) + 1.
	historyImage[0] = number new Images.
	historyImage[1] = number new Images.
	currentHistoryImageListIndex = 0.
	currentBestFitness = 0.0.
	
	baseImage init-with width 400 height 400.
	baseImage read-pixels at-x 0 at-y 0.
	
	finalImage init-with width 400 height 400.
	finalImage read-pixels at-x 0 at-y 0.
	
	for x=0,x<400,x++:
		for y=0,y<400,y++:
			finalImage set-alpha-pixel to 1.0 at-x x at-y y.
	
	foreach img in historyImage[0]:
		img init-with width 400 height 400.
	foreach img in historyImage[1]:
		img init-with width 400 height 400.
	...

+ to iterate:
	...
	if (currentTime >= pictureTime) || (currentTime >= changeTime):
	{
		pictureTime = (self get-time) + TIME_BETWEEN_SNAPSHOTS.
		historyImage[currentHistoryImageListIndex]{currentHistoryImageIndex} read-pixels at-x 0 at-y 0.
		currentHistoryImageIndex++.
	}
	...

+ to change-individuals:
	print "Generation:", currentGenerationIndex, "Individual:", currentIndividualIndex.
	currentPopulation{currentIndividualIndex} set-distance to |(creature get-location)|.

	if SAVE_BEST_OF_GEN_PICTURE:
	{
		if (currentPopulation{currentIndividualIndex} get-fitness) >= currentBestFitness:
		{
			currentBestFitness = (currentPopulation{currentIndividualIndex} get-fitness).
			currentHistoryImageListIndex = 1 - currentHistoryImageListIndex.
		}
	}
	currentIndividualIndex++.

	if currentIndividualIndex > ((currentSimulationConfig get-population-count) - 1):
	{
		self breed-new-population.
		currentGenerationIndex++.
		currentIndividualIndex = 0.
		currentBestFitness = 0.0.
	}
	self create-new-individual.
	currentHistoryImageIndex = 0.

In the above code, you may have noticed this line near the end of the init code:
finalImage set-alpha-pixel to 1.0 at-x x at-y y.

I had to do this because it seems that captured images appear to have 0.5 alpha by default (bug?).

Finally, this is the code that takes the images stored in the list associated with the best robot of the generation and generates & writes the blended image:

+ to breed-new-population:
	...
	if SAVE_BEST_OF_GEN_PICTURE:
	{
		currentHistoryImageList = historyImage[1 - currentHistoryImageListIndex].
		numHistoryImages = (currentSimulationConfig get-simulation-time)/TIME_BETWEEN_SNAPSHOTS.
		
		if currentHistoryImageIndex < numHistoryImages:
			currentHistoryImageList{currentHistoryImageIndex - 1} read-pixels at-x 0 at-y 0.
	
		for x=0,x<400,x++:
			for y=0,y<400,y++:
			{
				pixelColor = (baseImage get-rgb-pixel at-x x at-y y).
				finalImage set-rgb-pixel to pixelColor at-x x at-y y.
				for currentHistoryImageIndex=0,currentHistoryImageIndex<numHistoryImages,currentHistoryImageIndex++:
				{
					newPixelColor = (currentHistoryImageList{currentHistoryImageIndex} get-rgb-pixel at-x x at-y y).
					if newPixelColor != pixelColor:
						finalImage set-rgb-pixel to ((newPixelColor + (finalImage get-rgb-pixel at-x x at-y y)) * 0.5) at-x x at-y y.
				}
			}
		finalImage write to "$outputFilesFullPath/bestrobot_gen_$currentGenerationIndex~picture.png".
		currentHistoryImageIndex = 0.
	}
	...

This can take a few seconds, depending on the number and dimensions of the images in the list.

(Note: the "..." indicates that there is more code, just not related to the image generation)

Getting the viewport dimensions

jk wrote:I've added this for the next version. The Camera class now has methods get-width and get-height which will return this information.
...
I've added this too. The Real class will now have methods set-texture-scale-x and set-texture-scale-y to handle the texture scales independently.

Great! :D

Re: Getting the viewport dimensions

Very cool, PowerMacX,

I think I'm going to 'steal' that technique :wink:

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.