chevron-left chevron-right

[Augmented Reality] Jak stworzyć własną rzeczywistość?

Po dłuższej przerwie, związanej z sesją egzaminacyjną na uczelni, postanowiłem napisać nowy artykuł. Będzie on dotyczył niezwykłej technologii tworzenia własnej rzeczywistości - rozszerzonej rzeczywistości (ang. augmented reality).
Jak zapewne zauważyłeś/aś, w jednym z poprzednich postów zamieściłem filmik mojego autorstwa pokazującego próbkę możliwości tej technologii. Dzisiaj będę chciał przedstawić sposób na to, jak w łatwy i przystępny sposób zrobić taki efekt.
Ważne jest to, aby posiadać kamerę internetową, bo inaczej efekt nie będzie mógł zadziałać.
Muszę dodać, że jeśli znasz się na tworzeniu modeli trójwymiarowych i animacji trójwymiarowych, to będzie można stworzyć zdecydowanie lepsze efekty niż to co zostanie pokazane w tym artykule.

Na początek, muszę powiedzieć kilka słów odnośnie narzędzi jakich będziemy potrzebować. Jako że, efekt rozszerzonej rzeczywistości będę uzyskiwał za pomocą języka ActionScript, to potrzebujemy:

  • Programy: darmowy FlashDevelop lub płatny Adobe Flex Builder
  • bibliotekę PaperVision3D do generowania obiektów 3D
  • bibliotekę FLARTOOLKIT do generowania rozszerzonej rzeczywistości

Muszę dodać, że jeśli studiujesz na jakiejś uczelni, to możesz się postarać o darmową, studencką wersję Adobe Flex Buildera.
Należy pamiętać, aby dołożyć ścieżki do pobranych bibliotek w wybranym przez ciebie programie.
Jeśli będziesz mieć z tym problem, to napisz w komentarzach. Postaram się ci pomóc z tym problemem.

Biblioteka FLARTOOLKIT dostarcza nam kilka gotowych przykładów do wygenerowania. My natomiast będziemy modyfikować przykład o nazwie "Multiple SimpleCube", aby osiągnąć nasz efekt dwóch kostek o różnym wyglądzie i zachowaniu.

Na początek otwieramy plik o nazwie FLARTK_Example_Multiple_SimpleCube_PV3D.as. W nim musimy znaleźć linijkę z funkcją init. Podmienimy zawartość tej funkcji na następującą:

this.captureWidth 		= 320;
this.captureHeight 		= 240;
this.canvasWidth 		= 800;
this.canvasHeight 		= 600;
this.cameraParamFile 	= '../resources/Data/camera_para.dat';
 
this.markerPatternList 	= new Vector.<flarcode>();
 
this.markerPatternFileList 		= new Vector.<string>();
 
//tutaj definiujemy wzorce markerów, na bazie których będą się wyświetlały efekty
this.markerPatternFileList.push('../resources/Data/1.pat',
								'../resources/Data/2.pat',
								'../resources/Data/3.pat');
this.codeWidthList 		= new Vector.<number>();
this.codeWidthList.push( 80, 80);
this.paramLoad();
for (var i:int=0; i<markerpatternfilelist .length; i++) { }

Następnym krokiem będzie modyfikacja funkcji createObject:

var wmat:WireframeMaterial 	= new WireframeMaterial(_lightColor, 1, 2);
var _plane:Plane 			= new Plane(wmat, 80, 80); // 80mm x 80mm
_plane.rotationX 			= 0;
 
var light:PointLight3D 		= new PointLight3D();
light.x = 0;
light.y = 1000;
light.z = -1000;
 
_container 					= new DisplayObject3D();
_container.addChild(_plane);
 
//tutaj definiujemy materiały z których będzie się składać kostka
//pierwsza kostka będzie miała na sobie obrazki jpg
if (_num == 1)
{
	var front	:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/legia.jpg");
	var back	:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/korona.jpg");
	var left	:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/wisla.jpg");
	var right	:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/ruch.jpg");
	var top		:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/jaga.jpg");
	var bottom	:BitmapFileMaterial 	= new BitmapFileMaterial("../bin/loga/lech.jpg");
 
	var materialsList:MaterialsList 	= new MaterialsList();
	materialsList.addMaterial(front, 	"front");
	materialsList.addMaterial(right,	"right");
	materialsList.addMaterial(back,		"back");
	materialsList.addMaterial(left,		"left");
	materialsList.addMaterial(bottom,	"bottom");
	materialsList.addMaterial(top,		"top");
 
	//tutaj definiujemy nową kostkę i listę materiałów oraz zachowanie kostki
	_cube0 		= new Cube(materialsList, 80, 80, 80, 9, 9, 9);
	_cube0.y 	= 0;
	_cube0.x 	= 0;
	_cube0.z 	= 40;
	_cube0.roll( -90);		 
	_container.addChild(_cube0);
}
//kostka numer 2. Będzie się składała z kolorów. Kolory są zapisane w postaci heksadecymalnej (16-stkowej)
else if (_num == 2)
{
	var col1:ColorMaterial 			= new ColorMaterial(0x454545);
	var col2:ColorMaterial 			= new ColorMaterial(0xb30000);
	var col3:ColorMaterial 			= new ColorMaterial(0x463d21);
	var col4:ColorMaterial 			= new ColorMaterial(0xff3de4);
	var col5:ColorMaterial 			= new ColorMaterial(0xaa36fd);
	var col6:ColorMaterial 			= new ColorMaterial(0x9e9d45);
 
	var materialsList2:MaterialsList = new MaterialsList();
		materialsList2.addMaterial(col1,"front");
		materialsList2.addMaterial(col2,"right");
		materialsList2.addMaterial(col3,"back");
		materialsList2.addMaterial(col4,"left");
		materialsList2.addMaterial(col5,"bottom");
		materialsList2.addMaterial(col6,"top");
 
		//budowa drugiej kostki. Cube(lista materiałów, wysokość, szerokość, długość, dokładność, dokładność, dokładność)
		//dokładność odpowiada za jakość wyświetlanych tekstur
		_cube 	= new Cube(materialsList2, 40, 40, 40, 9, 9, 9);
		_cube.y = 0;
		_cube.x = 100;
		_cube.z = 0;
		_cube.roll( -90);
		_container.addChild(_cube);
}
else
{
	return null;
}
return _container;

Trzecim krokiem jest zmodyfikowanie funkcji start:

this.markerNodeList[0].addChild(this.createObject(0xFF0000, 0x660000, 1));
this.markerNodeList[1].addChild(this.createObject(0x0000FF, 0x000066, 2));
this.addEventListener(Event.ENTER_FRAME, this.run);

Czwartą funkcją, którą będziemy modyfikować będzie funkcja run:

this.capture.bitmapData.draw(this.video);
var detectedNumber:int 	= 0;
//wykrywanie markerów
try
{
	detectedNumber 		= this.detector.detectMarkerLite(this.raster, this._threshold);
}
catch (e:Error) {}
 
var i:int=0;
for (i = 0; i < this.markerPatternList.length; i++)
{
	this.markerList[i].isPrevDetect = this.markerList[i].isDetect;
	this.markerList[i].isDetect 	= false;
	this.markerList[i].confidence 	= 0.0;
}
for (i = 0; i < detectedNumber; i++)
{
	if (this.detector.getConfidence(i) > 0.5)
	{
		var detectMarkerID:int 	= this.detector.getARCodeIndex(i);
		var congidence:Number 	= this.detector.getConfidence(i);
		if (this.markerList[detectMarkerID].confidence < congidence)
		{
			this.markerList[detectMarkerID].confidence 	= congidence;
			this.detector.getTransformMatrix(i, this.markerList[detectMarkerID].resultMat);
			this.markerList[detectMarkerID].isDetect 	= true;
		}
	}
}
 
for (i = 0; i < this.markerPatternList.length; i++)
{
	var markerData:MarkerData = this.markerList[i];
	if (markerData.isDetect && markerData.isPrevDetect)
	{
		this.markerNodeList[i].setTransformMatrix(markerData.resultMat);
	}
	else if (markerData.isDetect)
	{
		this.markerNodeList[i].setTransformMatrix(markerData.resultMat);
		this.markerNodeList[i].visible = true;
	}
	else
	{
		this.markerNodeList[i].visible 	= false;
		var th:int						= this._threshold_detect.analyzeRaster(this.raster);
		this._threshold 				= (this._threshold + th) / 2;
	}
}
this.renderer.render();
 
//interakcja z markerami
//tutaj jest sprawdzanie czy markery są widzialne i ustawiona jest akcja w zależności od tego czy są 2 markery widzialne czy tylko 1 z nich
//dla każdej sytuacji jest inne zachowanie
if (this.markerNodeList[0].visible)
{
	_cube0.roll(10);
}
if (this.markerNodeList[0].visible && this.markerNodeList[1].visible )
{
	_cube0.yaw(5);
	var kierunek:Number3D = new Number3D(0, 10, 0);
	_cube.translate(10, kierunek);
}
if(this.markerNodeList[1].visible)
{
	_cube.pitch(10);
}

Ostatnią rzeczą jaką będziemy zmieniać w kodzie, to zmiana przykładu który będzie aktualnie wyświetlany.
Tego możemy dokonać w pliku Main.as. Gdzie musimy odkomentować (usuwamy //)

this.addChild(new FLARTK_Example_Multiple_SimpleCube_PV3D());

To tyle jeśli chodzi o kod programu. Teraz wystarczy wydrukować markery i uruchomić nasz kod w programie w którym go edytowaliśmy. Akceptujemy uruchomienie kamery internetowej i prezentujemy markery do kamery internetowej. Wtedy powinien się pojawić nasz efekt.

Pliki z tego artykułu są dostępne tutaj: augmented reality demo.