; docformat = 'rst'
;+
; Class to convert a 3D scene to an anaglyph.
;
; :Author:
; Michael Galloy
;-
;+
; Creates a combined image from images from the left and right eyes where the
; left eye is "shaded" red and the right eye is "shaded" blue.
;
; :Private:
;
; :Returns:
; bytarr(3, xsize, ysize)
;
; :Params:
; leftImage : in, optional, type="bytarr(3, xsize, ysize)"
; image from left eye
; rightImage : in, optional, type="bytarr(3, xsize, ysize)"
; image from right eye
;-
function mggr3dconverter::_combineImages, leftImage, rightImage
compile_opt strictarr
; define combined_image to the correct size
combinedImage = leftImage * 0B
dims = size(leftImage, /dimensions)
_leftImage = byte(total(fix(leftImage), 1) / 3)
_rightRight = byte(total(fix(rightImage), 1) / 3)
combinedImage[0, 0, 0] = Reform(_leftImage, 1, dims[1], dims[2])
combinedImage[1, 0, 0] = Reform(_rightRight, 1, dims[1], dims[2])
combinedImage[2, 0, 0] = Reform(_rightRight, 1, dims[1], dims[2])
return, combinedImage
end
;+
; Rotates "top-level" models of the given picture by the given number of
; degrees about the y-axis.
;
; :Private:
;
; :Params:
; picture : in, required, type=obj ref
; the view, viewgroup, or scene to be drawn
; degrees : in, required, type=float
; number of degrees to rotate "top-level" models
;-
pro mggr3dconverter::_rotateModels, picture, degrees
compile_opt strictarr
; if picture is a model then rotate it, but don't rotate models inside it
if (obj_isa(picture, 'IDLgrModel')) then begin
picture->rotate, [0, 1, 0], degrees
return
endif
if (obj_isa(picture, 'IDL_Container')) then begin
items = picture->get(/all, count=count)
for i = 0L, count - 1 do begin
self->_rotateModels, items[i], degrees
endfor
endif
end
;+
; Converts a standard object graphics picture to a view containing a 3D image.
;
; :Returns:
; IDLgrView object reference
;
; :Params:
; picture : in, optional, type=obj ref
; the view, viewgroup, or scene to be drawn; if the GRAPHICS_TREE
; property is set to a valid picture, then this argument must *not* be
; given
;-
function mggr3dconverter::convert, picture
compile_opt strictarr
; rotate "top-level" models for left eye
self->_rotateModels, picture, self.eyeSeparation / 2.
; draw picture to left eye buffer
self.buffer->draw, picture
; get data out of left eye buffer
oleftImage = self.buffer->read()
oleftImage->getProperty, data=leftImage
obj_destroy, oleftImage
; rotate "top-level" models for right eye
self->_rotateModels, picture, - self.eyeSeparation
; draw picture to right eye buffer
self.buffer->draw, picture
; get data out of left eye buffer
orightImage = self.buffer->read()
orightImage->getProperty, data=rightImage
obj_destroy, orightImage
; rotate "top-level" models back to center
self->_rotateModels, picture, self.eyeSeparation / 2.
combinedImage = self->_combineImages(leftImage, rightImage)
self.image->setProperty, data=combinedImage
return, self.view
end
;+
; Get properties of the converter.
;
; :Keywords:
; eye_separation : out, optional, type=float
; number of degrees of the cone formed by drawing lines from each eye to
; the origin
; dimensions : out, optional, type=intarr(2)
; dimensions of the window
;-
pro mggr3dconverter::getProperty, eye_separation=eyeSeparation, $
dimensions=dimensions
compile_opt strictarr
if (arg_present(eyeSeparation)) then begin
eyeSeparation = self.eyeSeparation
endif
if (arg_present(dimensions)) then begin
self.buffer->getProperty, dimensions=dimensions
endif
end
;+
; Set properties of the converter.
;
; :Keywords:
; eye_separation : in, optional, type=float
; number of degrees of the cone formed by drawing lines from each eye to
; the origin
; dimensions : in, optional, type=intarr(2)
; dimensions of the window
;-
pro mggr3dconverter::setProperty, eye_separation=eyeSeparation, $
dimensions=dimensions
compile_opt strictarr
if (n_elements(eye_separation) gt 0) then begin
self.eyeSeparation = eyeSeparation
endif
if (n_elements(dimensions) gt 0) then begin
self.view->setProperty, viewplace_rect=[0, 0, dimensions]
self.buffer->setProperty, dimensions=dimensions
endif
end
;+
; Free resources.
;-
pro mggr3dconverter::cleanup
compile_opt strictarr
obj_destroy, [self.view, self.buffer]
end
;+
; Initialize Window3D.
;
; :Returns:
; 1 for success, o/w for failure
;
; :Keywords:
; eye_separation : in, optional, type=float, default=4.0
; number of degrees of the cone formed by drawing lines from each eye to
; the origin
; dimensions {in}{required}{type=intarr(2)} dimensions of the window
; picture : out, optional, type=IDLgrView
; view which will contain a 3D image; the same view is updated each time
; that "convert_3d_picture" method is called
; _extra : in, optional, type=keywords
; keywords to IDLgrBuffer::init method are accepted
;-
function mggr3dconverter::init, eye_separation=eyeSeparation, $
dimensions=dimensions, picture=picture, _extra=e
compile_opt strictarr
self.eyeSeparation = n_elements(eyeSeparation) eq 0 ? 4.0 : eyeSeparation
self.buffer = obj_new('IDLgrBuffer', dimensions=dimensions, _extra=e)
self.view = obj_new('IDLgrView', viewplane_rect=[0, 0, dimensions])
model = obj_new('IDLgrModel')
self.view->add, model
self.image = obj_new('IDLgrImage')
model->add, self.image
return, 1
end
;+
; Helper object to transform a normal object graphics scene to a 3d picture.
;
; :Fields:
; eyeSeparation
; number of degrees of the cone formed by drawing lines from each eye to
; the origin
; buffer
; IDLgrBuffer to send left and right eye images to and extract
; view
; IDLgrView to contain the 3D image
; image
; IDLgrImage actually being displayed
;-
pro mggr3dconverter__define
compile_opt strictarr
define = { MGgr3dConverter, $
eyeSeparation: 0.0, $
buffer: obj_new(), $
view: obj_new(), $
image: obj_new() $
}
end