FLAR + MMD = dancing AR.

To get source code.

This code based on GPLv3.

Relational libraries are…
saqoosha/FLARToolKit/en – Spark project
papervision3d – Project Hosting on Google Code
BetweenAS3/en – Spark project
Thread/en – Spark project
Index of /garbage/b2ox/PMDViewer – ボカロプラス – SourceForge.JP

And source code is below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package org.tarotaro.flash.ar
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.*;
	import flash.media.Camera;
	import flash.media.Sound;
	import flash.media.Video;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	import org.b2ox.pv3d.MikuMikuDance;
	import org.libspark.betweenas3.BetweenAS3;
	import org.libspark.betweenas3.tweens.ITween;
	import org.libspark.flartoolkit.core.FLARCode;
	import org.libspark.flartoolkit.core.param.FLARParam;
	import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
	import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
	import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
	import org.libspark.flartoolkit.support.pv3d.FLARCamera3D;
	import org.libspark.flartoolkit.support.pv3d.FLARBaseNode;
	import org.libspark.thread.EnterFrameThreadExecutor;
	import org.libspark.thread.Thread;
	import org.papervision3d.objects.*;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.render.*;
	import org.papervision3d.view.Viewport3D;
 
	public class FLARMMD extends Sprite
	{
		protected var _param:FLARParam;
		protected var _code:FLARCode;
		protected var _raster:FLARRgbRaster_BitmapData;
		protected var _detector:FLARSingleMarkerDetector;
 
		protected var _webcam:Camera;
		protected var _video:Video;
		protected var _capture:Bitmap;
		protected var _base:Sprite;
		protected var _viewport:Viewport3D;
		protected var _camera3d:FLARCamera3D;
		protected var _scene:Scene3D;
		protected var _renderer:LazyRenderEngine;
		protected var _markerNode:FLARBaseNode;
 
		protected var _resultMat:FLARTransMatResult = new FLARTransMatResult();
 
		private var rootNode:DisplayObject3D = null;
		private var cameraDistance:Number = 1000;
		private var cameraDistanceMin:Number = 100;
		private var cameraAngleX:Number = 0;
		private var cameraAngleY:Number = 0;
 
		public var pmd:MikuMikuDance;
		private var glass:Boolean = false;
		private var punpun:Boolean = false;
		private var headset:Boolean = true;
 
		[Embed(source = 'assets/vocaloplus.png')] public var logoCls:Class;
		[Embed(source = 'assets/vocaloplus_eyecatch.mp3')] public var eyecatchCls:Class;
 
		[Embed(source = "assets/patt.hiro", mimeType = "application/octet-stream")]
		private var CodeData:Class;
 
		public function FLARMMD():void
		{
			if (!Thread.isReady) Thread.initialize(new EnterFrameThreadExecutor());
 
			// ポリゴン欠けは改善されるが負荷がとんでもない
			// renderer = new QuadrantRenderEngine(QuadrantRenderEngine.ALL_FILTERS);
 
			var logo:Bitmap = new logoCls();
			addChild(logo);
			var eyecatch:Sound = new eyecatchCls();
			eyecatch.play();
 
			loadingData();
		}
 
 
		//-------------------------------------------------
		// フレームレート表示用
		private var oldTimer:Number = getTimer();
		private var dispFps:TextField = new TextField();
		//-------------------------------------------------
 
		private function loadingData():void {
			pmd = new MikuMikuDance();
			pmd.loadPMD("Data/nanoha1052.zip://nanoha1052.pmd", 15, afterLoading);
			//pmd.loadPMD("latmiku2.zip://latmiku2w.pmd", 15, afterLoading);
			// BGcolor: #FDEFEA
			// BGcolor: #EC9F9F
		}
 
		private function afterLoading():void
		{
			pmd.loadVMD("Data/motions.zip://WiM-DIVA.vmd", "test",
			function ():void {
				// pmd.showBone();
				//pmd.y = -150;
				pmd.rotationX = 90;
				pmd.rotationZ = 90;
				pmd.scale = 0.5;
				pmd.looping = true;
				pmd.play();
				buildAR();
			} );
 
		}
		private function buildAR():void
		{
			var codeFile:ByteArray = new CodeData() as ByteArray;
 
			_param = new FLARParam();
			_param.changeScreenSize(320, 240);
			_code = new FLARCode(16,16,50,50);
			_code.loadARPatt(codeFile.readMultiByte(codeFile.length, "shift-jis"));
 
			// setup webcam
			_webcam = Camera.getCamera();
			if (!_webcam) {
				throw new Error('No webcam!!!!');
			}
			_webcam.setMode(320, 240, 30);
			_video = new Video(320, 240);
			_video.attachCamera(_webcam);
			_capture = new Bitmap(new BitmapData(320, 240, false, 0), PixelSnapping.AUTO, true);
 
			// setup ARToolkit
			_raster = new FLARRgbRaster_BitmapData(_capture.bitmapData);
			_detector = new FLARSingleMarkerDetector(_param, _code, 80);
			_detector.setContinueMode(true);
 
			_base = addChildAt(new Sprite(), 0) as Sprite;
 
			_capture.width = 640;
			_capture.height = 480;
			_base.addChild(_capture);
 
			_viewport = _base.addChild(new Viewport3D(320, 240)) as Viewport3D;
			_viewport.scaleX = 640 / 320;
			_viewport.scaleY = 480 / 240;
			_viewport.x = -4; // 4pix ???
 
			_camera3d = new FLARCamera3D(_param);
 
			_scene = new Scene3D();
			_markerNode = _scene.addChild(new FLARBaseNode()) as FLARBaseNode;
			_markerNode.addChild(pmd);
 
			_renderer = new LazyRenderEngine(_scene, _camera3d, _viewport);
 
			addEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
 
		private function _onEnterFrame(e:Event = null):void {
			_capture.bitmapData.draw(_video);
 
			var detected:Boolean = false;
			try {
				detected = _detector.detectMarkerLite(_raster, 80) && _detector.getConfidence() > 0.5;
			} catch (e:Error) {}
			trace(_detector.getConfidence());
			if (detected) {
				_detector.getTransformMatrix(_resultMat);
				_markerNode.setTransformMatrix(_resultMat);
				_markerNode.visible = true;
			} else {
				_markerNode.visible = false;
			}
 
			_renderer.render();
		}
 
	}
}
Ads

Ad

Ad

Share

  • Add this article to hatena bookmark
  • 0

Follow

Ads

Ad

Comments

  1. One says:

    Hi,

    Will you be able to provide the pattern file for this? I am trying to compile it but then the detection is not happening for the marker. Thanks for a method of using PMD and VMD.

  2. tarotarorg says:

    Hi, One.

    > Will you be able to provide the pattern file for this? I am trying to compile it but then the detection is not happening for the marker.
    Please use this pattern file.
    http://www.libspark.org/browser/as3/FLARToolKit/trunk/examples/tarotarorg/org/tarotaro/flash/ar/assets/patt.hiro?format=raw

    This is ARToolkit’s basic pattern “patt.hiro”.

    > hanks for a method of using PMD and VMD.
    PMDViewer is made by “Project vocaloplus” members.
    http://sourceforge.jp/projects/vocaloplus/

    They are very great. I use their works.

    Thank you.

  3. Sérgio Silva says:

    I tarotaro, thanks for the great example, I been able to put it to work on flex builder 3. Now I have one question, is it possible to add more than one vmp file to the same model? I see that there is a motion_name parameter one we load the vmp, is it possible to load a second vmp with another motion_name and then play either motion_name1 or motion_name2? If it is can you provide sample of loading and playing code.
    Great work
    Regards
    Sérgio

  4. Sérgio Silva says:

    Ok, I figure it out,
    for loading you must use:

    mmd.loadPMD(“../Data/nanoha1052.zip://nanoha1052.pmd”, 15, afterLoading1);

    private function afterLoading1():void
    {
    mmd.loadVMD(“../Data/grito.zip://grito.vmd”, “grito”);
    mmd.loadVMD(“../Data/normal.zip://normal.vmd”, “normal”);
    mmd.loadVMD(“../Data/motions.zip://WiM-DIVA.vmd”, “test”,
    function ():void {
    mmd.rotationX = 90;
    mmd.rotationZ = 90;
    mmd.scale = 0.5;
    mmd.y=50;
    mmd.x=100;
    mmd.looping = false;
    mmd.visible =false;
    // iniFLAR();
    } );
    }

    and after
    for changing motion use:

    mmd.changeMotion(“grito”);
    mmd.play();

  5. tarotarorg says:

    Hi, Sérgio Silva.

    I think you can do it.

    Thank you.

  6. zeomara says:

    Hello

    Visit this application and think about it for publicity purposes

    http://www.prodi3d.com/pagina_as_media/pag_as_ar.html

    Thanks:)

    PS
    Need plug in Flash player 9 or the most current …

  7. skyemoon says:

    hi,
    for this mmd.. what format does it use for the model?
    would you know if the whole ARTK+MMD works the same way as ARTK+VRML?
    cos i’m working on animating models for vrml but it doesnt accept bones or ik modifiers..

    Thanks

Leave a Comment

Your email address will not be published. Required fields are marked *