PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/example/flar/flash-sources/com/flar/FLARManager.as

https://github.com/t-ab/x3dom
ActionScript | 1182 lines | 780 code | 150 blank | 252 comment | 158 complexity | 5c338ef2d2ab56279064094acebec183 MD5 | raw file
  1. /*
  2. * PROJECT: FLARManager
  3. * http://transmote.com/flar
  4. * Copyright 2009, Eric Socolofsky
  5. * --------------------------------------------------------------------------------
  6. * This work complements FLARToolkit, developed by Saqoosha as part of the Libspark project.
  7. * http://www.libspark.org/wiki/saqoosha/FLARToolKit
  8. * FLARToolkit is Copyright (C)2008 Saqoosha,
  9. * and is ported from NYARToolkit, which is ported from ARToolkit.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this framework; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. * For further information please contact:
  26. * <eric(at)transmote.com>
  27. * http://transmote.com/flar
  28. *
  29. */
  30. package com.transmote.flar {
  31. import __AS3__.vec.Vector;
  32. import com.transmote.flar.marker.FLARMarker;
  33. import com.transmote.flar.marker.FLARMarkerEvent;
  34. import com.transmote.flar.pattern.FLARPattern;
  35. import com.transmote.flar.pattern.FLARPatternLoader;
  36. import com.transmote.flar.source.FLARCameraSource;
  37. import com.transmote.flar.source.FLARLoaderSource;
  38. import com.transmote.flar.source.IFLARSource;
  39. import com.transmote.flar.utils.FLARProxy;
  40. import com.transmote.flar.utils.smoother.FLARMatrixSmoother_Average;
  41. import com.transmote.flar.utils.smoother.IFLARMatrixSmoother;
  42. import com.transmote.flar.utils.threshold.DrunkWalkThresholdAdapter;
  43. import com.transmote.flar.utils.threshold.IThresholdAdapter;
  44. import flash.display.Bitmap;
  45. import flash.display.DisplayObject;
  46. import flash.display.DisplayObjectContainer;
  47. import flash.display.Sprite;
  48. import flash.events.ErrorEvent;
  49. import flash.events.Event;
  50. import flash.events.EventDispatcher;
  51. import flash.events.IOErrorEvent;
  52. import flash.events.SecurityErrorEvent;
  53. import flash.filters.BlurFilter;
  54. import flash.geom.Point;
  55. import flash.geom.Rectangle;
  56. import flash.net.URLLoader;
  57. import flash.net.URLLoaderDataFormat;
  58. import flash.net.URLRequest;
  59. import flash.utils.ByteArray;
  60. import flash.utils.getDefinitionByName;
  61. import flash.utils.getQualifiedClassName;
  62. import org.libspark.flartoolkit.FLARException;
  63. import org.libspark.flartoolkit.core.labeling.FLARLabeling_BitmapData;
  64. import org.libspark.flartoolkit.core.param.FLARParam;
  65. import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
  66. import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
  67. import org.libspark.flartoolkit.detector.FLARMultiMarkerDetector;
  68. import org.libspark.flartoolkit.detector.FLARMultiMarkerDetectorResult;
  69. /**
  70. * <p>
  71. * Manager for computer vision applications using FLARToolkit
  72. * (<a href="http://www.libspark.org/wiki/saqoosha/FLARToolKit/en" target="_blank">
  73. * http://www.libspark.org/wiki/saqoosha/FLARToolKit/en</a>).
  74. * </p>
  75. * <p>
  76. * Basic usage is as follows:
  77. * Pass a path to a camera parameters file and a list of FLARPatterns to the constructor.
  78. * Optionally pass an IFLARSource to use as the source image for marker detection;
  79. * FLARManager will by default create a FLARCameraSource that uses the first available camera.
  80. * Alternatively, FLARManager can be initialized using an xml file that specifies the above and other settings.
  81. * </p>
  82. * <p>
  83. * Assign event listeners to FLARManager for MARKER_ADDED,
  84. * MARKER_UPDATED, and MARKER_REMOVED FLARMarkerEvents.
  85. * These FLARMarkerEvents encapsulate the FLARMarker instances that they refer to.
  86. * Alternatively, it is possible to retrieve all active markers
  87. * directly from FLARManager, via FLARManager.activeMarkers.
  88. * </p>
  89. * <p>
  90. * FLARMarkers are simple objects that contain information about detected markers
  91. * provided by FLARToolkit. FLARManager maintains a list of active markers,
  92. * and updates the list and the markers within every frame.
  93. * </p>
  94. *
  95. * @author Eric Socolofsky
  96. * @url http://transmote.com/flar
  97. * @see com.transmote.flar.marker.FLARMarkerEvent
  98. * @see com.transmote.flar.source.FLARCameraSource
  99. * @see com.transmote.flar.utils.FLARProxy
  100. */
  101. public class FLARManager extends EventDispatcher {
  102. private static const ZERO_POINT:Point = new Point();
  103. // general management
  104. private var _activeMarkers:Vector.<FLARMarker>;
  105. private var _cameraParams:FLARParam;
  106. private var _flarSource:IFLARSource;
  107. // source and detection adjustment
  108. private var _threshold:Number = 80;
  109. private var _sampleBlurring:int = 1;
  110. private var _thresholdAdapter:IThresholdAdapter;
  111. // marker adjustment
  112. private var _markerUpdateThreshold:Number = 80;
  113. private var _markerRemovalDelay:int = 1;
  114. private var _smoothing:int = 3;
  115. private var _smoother:IFLARMatrixSmoother;
  116. // debugging
  117. private var _mirrorDisplay:Boolean;
  118. private var _thresholdSourceDisplay:Boolean;
  119. // pattern and marker management
  120. private var patternLoader:FLARPatternLoader;
  121. private var allPatterns:Vector.<FLARPattern>;
  122. private var markerDetector:FLARMultiMarkerDetector;
  123. private var flarRaster:FLARRgbRaster_BitmapData;
  124. private var thresholdSourceBitmap:Bitmap;
  125. private var markersPendingRemoval:Vector.<FLARMarker>;
  126. // marker adjustment (private)
  127. private var enterframer:Sprite;
  128. private var averageConfidence:Number = FLARPattern.DEFAULT_MIN_CONFIDENCE;
  129. private var averageMinConfidence:Number = FLARPattern.DEFAULT_MIN_CONFIDENCE;
  130. private var sampleBlurFilter:BlurFilter;
  131. // application state
  132. private var bInited:Boolean;
  133. private var bCameraParamsLoaded:Boolean;
  134. private var bPatternsLoaded:Boolean;
  135. private var bActive:Boolean;
  136. private var bVerbose:Boolean;
  137. /**
  138. * Constructor.
  139. * Initialize FLARManager by passing in a configuration file path.
  140. *
  141. * @param flarConfigPath path to the FLARManager configuration xml file.
  142. */
  143. public function FLARManager (flarConfigPath:String="") {
  144. this._flarSource = new FLARCameraSource();
  145. if (flarConfigPath != "") {
  146. this.initFromFile(flarConfigPath);
  147. }
  148. }
  149. /**
  150. * the old-fashioned way to initialize FLARManager.
  151. * the preferred method is to use an external xml configuration file,
  152. * and to pass its path into the FLARManager constructor.
  153. *
  154. * @param cameraParamsPath camera parameters filename.
  155. * @param patterns list of FLARPatterns to detect.
  156. * @param source IFLARSource instance to use as source image for marker detection.
  157. * if null, FLARManager will create a camera capture source.
  158. */
  159. public function initManual (cameraParamsPath:String, patterns:Vector.<FLARPattern>, source:IFLARSource=null) :void {
  160. if (source) {
  161. this._flarSource = source;
  162. this._mirrorDisplay = source.mirrored;
  163. } else {
  164. this._flarSource = new FLARCameraSource();
  165. }
  166. this.init(cameraParamsPath, patterns);
  167. }
  168. /**
  169. * load FLARManager configuration from an xml file.
  170. * note, this method no longer needs to be called manually;
  171. * simply passing the configuration file path into the constructor
  172. * will also initialize correctly. this method is here for legacy support only.
  173. *
  174. * @param flarConfigPath path to the FLARManager configuration xml file.
  175. */
  176. public function initFromFile (flarConfigPath:String) :void {
  177. var loader:URLLoader = new URLLoader();
  178. loader.addEventListener(IOErrorEvent.IO_ERROR, this.onFlarConfigLoadError);
  179. loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onFlarConfigLoadError);
  180. loader.addEventListener(Event.COMPLETE, this.onFlarConfigLoaded);
  181. loader.load(new URLRequest(flarConfigPath));
  182. }
  183. /**
  184. * init from an XML object in Flash.
  185. * this can be useful when dynamically generating an XML file at runtime,
  186. * such as via a middleware request.
  187. */
  188. public function initFromXML (flarConfigXML:XML) :void {
  189. this.parseFlarConfigFile(flarConfigXML);
  190. this.dispatchEvent(new Event(Event.COMPLETE));
  191. }
  192. //-----<ACCESSORS>---------------------------------//
  193. /**
  194. * Vector of all currently-active markers.
  195. */
  196. public function get activeMarkers () :Vector.<FLARMarker> {
  197. return this._activeMarkers;
  198. }
  199. /**
  200. * FLARParam used by this FLARManager.
  201. * can be used to instantiate a FLARCamera3D for use with Papervision.
  202. */
  203. public function get cameraParams () :FLARParam {
  204. return this._cameraParams;
  205. }
  206. /**
  207. * IFLARSource instance this FLARManager is using as the source image for marker detection.
  208. */
  209. public function get flarSource () :IFLARSource {
  210. return this._flarSource;
  211. }
  212. /**
  213. * reference to FLARCameraSource used in this application.
  214. * if this application does not use a camera, returns null.
  215. */
  216. public function get flarCameraSource () :FLARCameraSource {
  217. return this._flarSource as FLARCameraSource;
  218. }
  219. /**
  220. * pixels in source image with a brightness <= to this.threshold are candidates for marker outline detection.
  221. * increase to increase likelihood of marker detection;
  222. * increasing too high will cause engine to incorrectly detect non-existent markers.
  223. * defaults to 80 (values can range from 0 to 255).
  224. */
  225. public function get threshold () :int {
  226. return this._threshold;
  227. }
  228. public function set threshold (val:int) :void {
  229. if (this.bVerbose && !this.thresholdAdapter) {
  230. trace("[FLARManager] threshold: "+ val);
  231. }
  232. this._threshold = val;
  233. }
  234. /**
  235. * IFLARThresholdAdapter used to automate threshold changes.
  236. *
  237. * adaptive thresholding can result in better marker detection across a range of illumination.
  238. * this is desirable for applications with low lighting, or in which the developer has little control
  239. * over lighting conditions, such as with web applications.
  240. *
  241. * note that adaptive thresholding may cause slower performance in very dark environments.
  242. * this happens because a low threshold creates an image with large black areas,
  243. * and images with a lot of black can cause slowdown in FLARToolkit's labeling process
  244. * (FLARLabeling_BitmapData.labeling()). in this case, thresholdAdapter should be set to null.
  245. *
  246. * the default threshold adapter is DrunkWalkThresholdAdapter, but developers can implement their own
  247. * algorithms for adaptive thresholding. to do so, implement the IThresholdAdapter interface.
  248. */
  249. public function get thresholdAdapter () :IThresholdAdapter {
  250. return this._thresholdAdapter;
  251. }
  252. public function set thresholdAdapter (val:IThresholdAdapter) :void {
  253. if (this.bVerbose) {
  254. trace("[FLARManager] threshold adapter: "+ flash.utils.getQualifiedClassName(val));
  255. }
  256. this._thresholdAdapter = val;
  257. }
  258. /**
  259. * the amount of blur applied to the source image
  260. * before sending to FLARToolkit for marker detection.
  261. * higher values increase framerate, but reduce detection accuracy.
  262. * value must be zero or greater. the default value is 2.
  263. */
  264. public function get sampleBlurring () :int {
  265. return this._sampleBlurring;
  266. }
  267. public function set sampleBlurring (val:int) :void {
  268. if (!this.sampleBlurFilter) {
  269. this.sampleBlurFilter = new BlurFilter();
  270. }
  271. if (val <= 0) {
  272. val = 0;
  273. this.sampleBlurFilter.blurX = this.sampleBlurFilter.blurY = 0;
  274. } else {
  275. this.sampleBlurFilter.blurX = this.sampleBlurFilter.blurY = Math.pow(2, val-1);
  276. }
  277. this._sampleBlurring = val;
  278. if (this.bVerbose) {
  279. trace("[FLARManager] sample blurring: "+ val);
  280. }
  281. }
  282. /**
  283. * provides direct access to FLARLabeling_BitmapData.minimumLabelSize,
  284. * which is the minimum size (width*height) a dark area of the source image must be
  285. * in order to become a candidate for marker outline detection.
  286. * higher values result in faster performance,
  287. * but poorer marker detection at smaller sizes (as they appear on-screen).
  288. * defaults to 100.
  289. */
  290. public function get minimumLabelSize () :Number {
  291. return FLARLabeling_BitmapData.minimumLabelSize;
  292. }
  293. public function set minimumLabelSize (val:Number) :void {
  294. if (this.bVerbose) {
  295. trace("[FLARManager] minimum label size: "+ val);
  296. }
  297. FLARLabeling_BitmapData.minimumLabelSize = val;
  298. }
  299. /**
  300. * if a detected marker is within this distance (pixels) from an active marker,
  301. * FLARManager considers the detected marker to be an update of the active marker.
  302. * else, the detected marker is a new marker.
  303. * increase this value to accommodate faster-moving markers;
  304. * decrease it to accommodate more markers on-screen at once.
  305. */
  306. public function get markerUpdateThreshold () :Number {
  307. return this._markerUpdateThreshold;
  308. }
  309. public function set markerUpdateThreshold (val:Number) :void {
  310. if (this.bVerbose) {
  311. trace("[FLARManager] marker update threshold: "+ val);
  312. }
  313. this._markerUpdateThreshold = val;
  314. }
  315. /**
  316. * number of frames after removal that a marker will persist before dispatching a MARKER_REMOVED event.
  317. * if a marker of the same pattern appears within <tt>markerUpdateThreshold</tt> pixels
  318. * of the point of removal, before <tt>markerRemovalDelay</tt> frames have elapsed,
  319. * the marker will be reinstated as if it was never removed.
  320. *
  321. * the default value is 1.
  322. */
  323. public function get markerRemovalDelay () :int {
  324. return this._markerRemovalDelay;
  325. }
  326. public function set markerRemovalDelay (val:int) :void {
  327. if (this.bVerbose) {
  328. trace("[FLARManager] marker removal delay: "+ val);
  329. }
  330. this._markerRemovalDelay = val;
  331. }
  332. /**
  333. * apply a smoothing algorithm to transformation matrices generated by FLARToolkit.
  334. * smoothing is equal to the number of frames over which FLARManager
  335. * will average transformation matrices; the larger the number, the smoother the animation,
  336. * and the slower the response time between marker position/orientation changes.
  337. * a value of 0 turns smoothing off.
  338. */
  339. public function get smoothing () :int {
  340. return this._smoothing;
  341. }
  342. public function set smoothing (val:int) :void {
  343. if (this.bVerbose) {
  344. trace("[FLARManager] smoothing: "+ val);
  345. }
  346. this._smoothing = val;
  347. }
  348. /**
  349. * IFLARMatrixSmoother to use to apply smoothing to transformation matrices generated by FLARToolkit.
  350. */
  351. public function get smoother () :IFLARMatrixSmoother {
  352. return this._smoother;
  353. }
  354. public function set smoother (val:IFLARMatrixSmoother) :void {
  355. if (this.bVerbose) {
  356. trace("[FLARManager] smoother "+ flash.utils.getQualifiedClassName(val));
  357. }
  358. this._smoother = val;
  359. }
  360. /**
  361. * set to true to flip the camera image horizontally;
  362. * this value is passed on to this.flarSource;
  363. * note that if an IFLARSource is specified after mirrorDisplay is set,
  364. * the 'mirrored' property of the new IFLARSource will overwrite this value.
  365. */
  366. public function get mirrorDisplay () :Boolean {
  367. return this._mirrorDisplay;
  368. }
  369. public function set mirrorDisplay (val:Boolean) :void {
  370. if (this.bVerbose) {
  371. trace("[FLARManager] mirror display: "+ val);
  372. }
  373. this._mirrorDisplay = val;
  374. if (this.flarSource) {
  375. this.flarSource.mirrored = this._mirrorDisplay;
  376. }
  377. }
  378. /**
  379. * display the source BitmapData used by FLARToolkit post-thresholding.
  380. * useful for debugging.
  381. */
  382. public function get thresholdSourceDisplay () :Boolean {
  383. return this._thresholdSourceDisplay;
  384. }
  385. public function set thresholdSourceDisplay (val:Boolean) :void {
  386. if (this.bVerbose) {
  387. trace("[FLARManager] threshold source display: "+ val);
  388. }
  389. this._thresholdSourceDisplay = val;
  390. if (this._thresholdSourceDisplay) {
  391. try {
  392. if (!this.thresholdSourceBitmap) {
  393. if (!this.markerDetector.thresholdedBitmapData) {
  394. throw new Error("Error initializing FLARMultiMarkerDetector; thresholdedBitmapData not inited.");
  395. }
  396. this.thresholdSourceBitmap = new Bitmap(this.markerDetector.thresholdedBitmapData);
  397. Sprite(this._flarSource).addChild(this.thresholdSourceBitmap);
  398. }
  399. } catch (e:Error) {
  400. this.thresholdSourceBitmap = null;
  401. return;
  402. }
  403. }
  404. }
  405. /**
  406. * the number of patterns loaded for detection.
  407. */
  408. public function get numLoadedPatterns () :int {
  409. return this.patternLoader.loadedPatterns.length;
  410. }
  411. /**
  412. * true if this FLARManager instance is active and currently processing marker detection.
  413. */
  414. public function get isActive () :Boolean {
  415. return this.bActive;
  416. }
  417. public function set isActive (val:Boolean) :void {
  418. trace("[FLARManager] "+ (val ? "activated" : "deactivated"));
  419. if (val) {
  420. this.activate();
  421. } else {
  422. this.deactivate();
  423. }
  424. }
  425. /**
  426. * if true, FLARManager will output configuration changes to the console.
  427. */
  428. public function get verbose () :Boolean {
  429. return this.bVerbose;
  430. }
  431. public function set verbose (val:Boolean) :void {
  432. this.bVerbose = val;
  433. trace("[FLARManager] verbosity "+ (val ? "ON" : "OFF"));
  434. }
  435. //-----</ACCESSORS>--------------------------------//
  436. //-----<PUBLIC METHODS>----------------------------//
  437. /**
  438. * begin detecting markers once per frame.
  439. * this method is called automatically on initialization.
  440. * @return false if FLARManager is not yet initialized; else true.
  441. */
  442. public function activate () :Boolean {
  443. if (!this.bInited) { return false; }
  444. if (this.bActive) { return true; }
  445. this.bActive = true;
  446. if (this._flarSource is FLARProxy) {
  447. // activate FLARProxy
  448. var flarProxy:FLARProxy = this._flarSource as FLARProxy;
  449. flarProxy.activate();
  450. flarProxy.addEventListener(FLARMarkerEvent.MARKER_ADDED, this.onProxyMarkerAdded);
  451. flarProxy.addEventListener(FLARMarkerEvent.MARKER_UPDATED, this.onProxyMarkerUpdated);
  452. flarProxy.addEventListener(FLARMarkerEvent.MARKER_REMOVED, this.onProxyMarkerRemoved);
  453. } else {
  454. // activate normally
  455. if (!this.enterframer) {
  456. this.enterframer = new Sprite();
  457. }
  458. this.enterframer.removeEventListener(Event.ENTER_FRAME, this.onEnterFrame);
  459. this.enterframer.addEventListener(Event.ENTER_FRAME, this.onEnterFrame, false, 0, true);
  460. }
  461. this._activeMarkers = new Vector.<FLARMarker>();
  462. this.markersPendingRemoval = new Vector.<FLARMarker>();
  463. return true;
  464. }
  465. /**
  466. * stop detecting markers.
  467. * removes all currently-active markers.
  468. * enterframe loop continues, to update video.
  469. */
  470. public function deactivate () :void {
  471. if (!this.bActive) {
  472. return;
  473. }
  474. this.bActive = false;
  475. if (this._flarSource is FLARProxy) {
  476. // deactivate FLARProxy
  477. var flarProxy:FLARProxy = this._flarSource as FLARProxy;
  478. flarProxy.deactivate();
  479. flarProxy.addEventListener(FLARMarkerEvent.MARKER_ADDED, this.onProxyMarkerAdded);
  480. flarProxy.addEventListener(FLARMarkerEvent.MARKER_UPDATED, this.onProxyMarkerUpdated);
  481. flarProxy.addEventListener(FLARMarkerEvent.MARKER_REMOVED, this.onProxyMarkerRemoved);
  482. }
  483. if (this._activeMarkers) {
  484. var i:int = this._activeMarkers.length;
  485. while (i--) {
  486. // remove all active markers
  487. this.removeMarker(this._activeMarkers[i]);
  488. }
  489. this._activeMarkers = null;
  490. }
  491. if (this.markersPendingRemoval) {
  492. i = this.markersPendingRemoval.length;
  493. while (i--) {
  494. this.markersPendingRemoval[i].dispose();
  495. }
  496. this.markersPendingRemoval = null;
  497. }
  498. }
  499. /**
  500. * halts all processes and frees this instance for garbage collection.
  501. */
  502. public function dispose () :void {
  503. this.deactivate();
  504. this.enterframer.removeEventListener(Event.ENTER_FRAME, this.onEnterFrame);
  505. this.enterframer = null;
  506. this._cameraParams = null;
  507. this._flarSource.dispose();
  508. var flarSourceDO:DisplayObject = this._flarSource as DisplayObject;
  509. if (flarSourceDO && flarSourceDO.parent) {
  510. flarSourceDO.parent.removeChild(flarSourceDO);
  511. }
  512. this._flarSource = null;
  513. this._thresholdAdapter.dispose();
  514. this._thresholdAdapter = null;
  515. this._smoother = null;
  516. this.patternLoader.dispose();
  517. this.patternLoader = null;
  518. this.allPatterns = null;
  519. // NOTE: FLARToolkit classes do not implement any disposal functionality,
  520. // and will likely not be removed from memory on FLARManager disposal.
  521. //this.markerDetector.dispose();
  522. this.markerDetector = null;
  523. this.flarRaster.bitmapData.dispose();
  524. this.flarRaster = null;
  525. if (this.thresholdSourceBitmap) {
  526. this.thresholdSourceBitmap.bitmapData.dispose();
  527. }
  528. this.thresholdSourceBitmap = null;
  529. this.sampleBlurFilter = null;
  530. }
  531. //-----</PUBLIC METHODS>---------------------------//
  532. //-----<MARKER DETECTION>----------------------------//
  533. private function onEnterFrame (evt:Event) :void {
  534. if (!this.updateSource()) { return; }
  535. if (!this.bActive) { return; }
  536. this.ageRemovedMarkers();
  537. this.performSourceAdjustments();
  538. this.detectMarkers();
  539. }
  540. private function updateSource () :Boolean {
  541. try {
  542. // ensure this.flarRaster has been initialized
  543. if (this.flarRaster == null) {
  544. this.flarRaster = new FLARRgbRaster_BitmapData(this.flarSource.source);
  545. }
  546. } catch (e:Error) {
  547. // this.flarSource not yet fully initialized
  548. return false;
  549. }
  550. // update source image
  551. this.flarSource.update();
  552. return true;
  553. }
  554. private function ageRemovedMarkers () :void {
  555. // remove all markers older than this.markerRemovalDelay.
  556. var i:uint = this.markersPendingRemoval.length;
  557. var removedMarker:FLARMarker;
  558. while (i--) {
  559. removedMarker = this.markersPendingRemoval[i];
  560. if (removedMarker.incrementRemovalAge() > this.markerRemovalDelay) {
  561. this.removeMarker(removedMarker);
  562. }
  563. }
  564. }
  565. private function performSourceAdjustments () :void {
  566. if (this.thresholdAdapter) {
  567. if (this.thresholdAdapter.runsEveryFrame) {
  568. // adjust threshold every frame.
  569. this.threshold = this.thresholdAdapter.calculateThreshold(this.flarRaster.bitmapData, this.threshold);
  570. } else {
  571. // adjust threshold only when confidence is low (poor marker detection).
  572. if (this.averageConfidence <= this.averageMinConfidence) {
  573. this.threshold = this.thresholdAdapter.calculateThreshold(this.flarRaster.bitmapData, this.threshold);
  574. } else {
  575. this.thresholdAdapter.resetCalculations(this.threshold);
  576. }
  577. }
  578. this.averageConfidence = this.averageMinConfidence = 0;
  579. }
  580. if (this.sampleBlurring > 0) {
  581. // apply blur filter to combine and reduce number of black areas in image to be labeled.
  582. this.flarRaster.bitmapData.applyFilter(this.flarRaster.bitmapData, this.flarSource.sourceSize, ZERO_POINT, this.sampleBlurFilter);
  583. }
  584. }
  585. private function detectMarkers () :void {
  586. var numFoundMarkers:int = 0;
  587. try {
  588. // detect marker(s)
  589. numFoundMarkers = this.markerDetector.detectMarkerLite(this.flarRaster, this.threshold);
  590. } catch (e:FLARException) {
  591. // error in FLARToolkit processing; send to console
  592. trace(e);
  593. return;
  594. }
  595. var activeMarker:FLARMarker;
  596. var i:uint;
  597. if (numFoundMarkers == 0) {
  598. // if no markers found, remove any existing markers and exit
  599. i = this._activeMarkers.length;
  600. while (i--) {
  601. this.queueMarkerForRemoval(this._activeMarkers[i]);
  602. }
  603. return;
  604. }
  605. // build list of detected markers
  606. var detectedMarkers:Vector.<FLARMarker> = new Vector.<FLARMarker>();
  607. var detectedMarkerResult:FLARMultiMarkerDetectorResult;
  608. var patternIndex:int;
  609. var detectedPattern:FLARPattern;
  610. var confidence:Number;
  611. var confidenceSum:Number = 0;
  612. var minConfidenceSum:Number = 0;
  613. var transmat:FLARTransMatResult;
  614. i = numFoundMarkers;
  615. while (i--) {
  616. detectedMarkerResult = this.markerDetector.getResult(i);
  617. patternIndex = this.markerDetector.getARCodeIndex(i);
  618. detectedPattern = this.allPatterns[patternIndex];
  619. confidence = this.markerDetector.getConfidence(i);
  620. confidenceSum += confidence;
  621. minConfidenceSum += detectedPattern.minConfidence;
  622. if (confidence < detectedPattern.minConfidence) {
  623. // detected marker's confidence is below the minimum required confidence for its pattern.
  624. continue;
  625. }
  626. transmat = new FLARTransMatResult();
  627. try {
  628. this.markerDetector.getTransmationMatrix(i, transmat);
  629. } catch (e:Error) {
  630. // FLARException happens with rotationX of approx -60 and +60, and rotY&Z of 0.
  631. // not sure why...
  632. continue;
  633. }
  634. detectedMarkers.push(new FLARMarker(detectedMarkerResult, transmat, this.flarSource, detectedPattern));
  635. }
  636. this.averageConfidence = confidenceSum / numFoundMarkers;
  637. this.averageMinConfidence = minConfidenceSum / numFoundMarkers;
  638. // compare detected markers against active markers
  639. i = detectedMarkers.length;
  640. var j:uint, k:uint;
  641. var detectedMarker:FLARMarker;
  642. var closestMarker:FLARMarker;
  643. var closestDist:Number = Number.POSITIVE_INFINITY;
  644. var dist:Number;
  645. var updatedMarkers:Vector.<FLARMarker> = new Vector.<FLARMarker>();
  646. var newMarkers:Vector.<FLARMarker> = new Vector.<FLARMarker>();
  647. var removedMarker:FLARMarker;
  648. var bRemovedMarkerMatched:Boolean = false;
  649. while (i--) {
  650. j = this._activeMarkers.length;
  651. detectedMarker = detectedMarkers[i];
  652. closestMarker = null;
  653. closestDist = Number.POSITIVE_INFINITY;
  654. while (j--) {
  655. activeMarker = this._activeMarkers[j];
  656. if (detectedMarker.patternId == activeMarker.patternId) {
  657. dist = Point.distance(detectedMarker.centerpoint3D, activeMarker.targetCenterpoint3D);
  658. if (dist < closestDist && dist < this._markerUpdateThreshold) {
  659. closestMarker = activeMarker;
  660. closestDist = dist;
  661. }
  662. }
  663. }
  664. if (closestMarker) {
  665. // updated marker
  666. closestMarker.copy(detectedMarker);
  667. detectedMarker.dispose();
  668. if (this._smoothing) {
  669. if (!this._smoother) {
  670. // TODO: log as a WARN-level error
  671. trace("no smoother set; specify FLARManager.smoother to enable smoothing.");
  672. } else {
  673. closestMarker.applySmoothing(this._smoother, this._smoothing);
  674. }
  675. }
  676. updatedMarkers.push(closestMarker);
  677. // if closestMarker is pending removal, restore it.
  678. k = this.markersPendingRemoval.length;
  679. while (k--) {
  680. if (this.markersPendingRemoval[k] == closestMarker) {
  681. closestMarker.resetRemovalAge();
  682. this.markersPendingRemoval.splice(k, 1);
  683. }
  684. }
  685. this.dispatchEvent(new FLARMarkerEvent(FLARMarkerEvent.MARKER_UPDATED, closestMarker));
  686. } else {
  687. // new marker
  688. newMarkers.push(detectedMarker);
  689. detectedMarker.setSessionId();
  690. this.dispatchEvent(new FLARMarkerEvent(FLARMarkerEvent.MARKER_ADDED, detectedMarker));
  691. }
  692. }
  693. i = this._activeMarkers.length;
  694. while (i--) {
  695. activeMarker = this._activeMarkers[i];
  696. if (updatedMarkers.indexOf(activeMarker) == -1) {
  697. // if activeMarker was not updated, queue it for removal.
  698. this.queueMarkerForRemoval(activeMarker);
  699. }
  700. }
  701. this._activeMarkers = this._activeMarkers.concat(newMarkers);
  702. }
  703. private function queueMarkerForRemoval (marker:FLARMarker) :void {
  704. if (this.markersPendingRemoval.indexOf(marker) == -1) {
  705. this.markersPendingRemoval.push(marker);
  706. }
  707. }
  708. private function removeMarker (marker:FLARMarker) :void {
  709. var i:uint = this._activeMarkers.indexOf(marker);
  710. if (i >= 0) {
  711. this._activeMarkers.splice(i, 1);
  712. }
  713. i = this.markersPendingRemoval.indexOf(marker);
  714. if (i >= 0) {
  715. this.markersPendingRemoval.splice(i, 1);
  716. }
  717. this.dispatchEvent(new FLARMarkerEvent(FLARMarkerEvent.MARKER_REMOVED, marker));
  718. marker.dispose();
  719. }
  720. private function onProxyMarkerAdded (evt:FLARMarkerEvent) :void {
  721. this.dispatchEvent(evt);
  722. }
  723. private function onProxyMarkerUpdated (evt:FLARMarkerEvent) :void {
  724. this.dispatchEvent(evt);
  725. }
  726. private function onProxyMarkerRemoved (evt:FLARMarkerEvent) :void {
  727. this.dispatchEvent(evt);
  728. }
  729. //-----</MARKER DETECTION>---------------------------//
  730. //-----<INITIALIZATION>----------------------------//
  731. private function onFlarConfigLoadError (evt:Event) :void {
  732. var errorText:String = "character list load error.";
  733. if (evt is IOErrorEvent) {
  734. errorText = IOErrorEvent(evt).text;
  735. } else if (evt is SecurityErrorEvent) {
  736. errorText = SecurityErrorEvent(evt).text;
  737. }
  738. this.onFlarConfigLoaded(evt, new Error(errorText));
  739. }
  740. private function onFlarConfigLoaded (evt:Event, error:Error=null) :void {
  741. var loader:URLLoader = evt.target as URLLoader;
  742. loader.removeEventListener(IOErrorEvent.IO_ERROR, this.onFlarConfigLoadError);
  743. loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onFlarConfigLoadError);
  744. loader.removeEventListener(Event.COMPLETE, this.onFlarConfigLoaded);
  745. if (error) { throw error; }
  746. this.parseFlarConfigFile(new XML(loader.data as String));
  747. this.dispatchEvent(new Event(Event.COMPLETE));
  748. }
  749. private function parseFlarConfigFile (configFileXML:XML) :void {
  750. // source settings
  751. var sourceInitStruct:SourceInitStruct = new SourceInitStruct();
  752. var sourceWidth:int = parseInt(configFileXML.flarSourceSettings.@sourceWidth);
  753. if (!isNaN(sourceWidth) && sourceWidth > 0) {
  754. sourceInitStruct.sourceWidth = sourceWidth;
  755. }
  756. var sourceHeight:int = parseInt(configFileXML.flarSourceSettings.@sourceHeight);
  757. if (!isNaN(sourceHeight) && sourceHeight > 0) {
  758. sourceInitStruct.sourceHeight = sourceHeight;
  759. }
  760. var displayWidth:int = parseInt(configFileXML.flarSourceSettings.@displayWidth);
  761. if (!isNaN(displayWidth) && displayWidth > 0) {
  762. sourceInitStruct.displayWidth = displayWidth;
  763. }
  764. var displayHeight:int = parseInt(configFileXML.flarSourceSettings.@displayHeight);
  765. if (!isNaN(displayHeight) && displayHeight > 0) {
  766. sourceInitStruct.displayHeight = displayHeight;
  767. }
  768. var framerate:Number = parseFloat(configFileXML.flarSourceSettings.@framerate);
  769. if (!isNaN(framerate) && framerate > 0) {
  770. sourceInitStruct.framerate = framerate;
  771. }
  772. var downsampleRatio:Number = parseFloat(configFileXML.flarSourceSettings.@downsampleRatio);
  773. if (!isNaN(downsampleRatio) && downsampleRatio > 0) {
  774. sourceInitStruct.downsampleRatio = downsampleRatio;
  775. }
  776. sourceInitStruct.loaderPath = configFileXML.flarSourceSettings.@loaderPath;
  777. sourceInitStruct.useProxy = configFileXML.flarSourceSettings.@useProxy == "true";
  778. // miscellaneous FLARManager settings
  779. var mirrorDisplayStr:String = configFileXML.flarManagerSettings.@mirrorDisplay.toString();
  780. this.mirrorDisplay = mirrorDisplayStr && mirrorDisplayStr.toLowerCase() == "true";
  781. var markerUpdateThresholdVal:Number = parseFloat(configFileXML.flarManagerSettings.@markerUpdateThreshold);
  782. if (!isNaN(markerUpdateThresholdVal) && markerUpdateThresholdVal > 0) {
  783. this.markerUpdateThreshold = markerUpdateThresholdVal;
  784. }
  785. var smootherName:String = configFileXML.flarManagerSettings.smoother.@className;
  786. if (smootherName != "") {
  787. if (smootherName.indexOf(".") == -1) {
  788. smootherName = "com.transmote.flar.utils.smoother." + smootherName;
  789. }
  790. try {
  791. var SmootherClass:Class = flash.utils.getDefinitionByName(smootherName) as Class;
  792. this.smoother = new SmootherClass();
  793. } catch (e:Error) {
  794. trace("error creating smoother with className:"+ smootherName +". ensure the config file specifies a fully-qualified class name, or that the class is in the com.transmote.flar.utils.smoother package. also, be sure to create a reference to the class anywhere in the project, to ensure it is compiled into the SWF.");
  795. }
  796. if (this.smoother) {
  797. var smootherParamsList:XMLList = configFileXML.flarManagerSettings.smoother[0].@*;
  798. if (smootherParamsList.length() > 1) {
  799. try {
  800. var smootherParamsObj:Object = new Object();
  801. var paramName:String;
  802. for (var i:int=0; i<smootherParamsList.length(); i++) {
  803. paramName = smootherParamsList[i].name();
  804. if (paramName == "className") { continue; }
  805. smootherParamsObj[paramName] = smootherParamsList[i].toString();
  806. }
  807. this.smoother.initFromXML(smootherParamsObj);
  808. } catch (e:Error) {
  809. trace("error applying smoother params:"+ smootherParamsList);
  810. }
  811. }
  812. }
  813. }
  814. var smoothingVal:int = parseInt(configFileXML.flarManagerSettings.@smoothing);
  815. if (!isNaN(smoothingVal) && smoothingVal > 0) {
  816. this.smoothing = smoothingVal;
  817. }
  818. if (configFileXML.flarManagerSettings.@adaptiveThresholding.toString().toLowerCase() != "") {
  819. trace("adaptiveThresholding attribute is deprecated as of v0.6. specify a thresholdAdapter instead, or omit to use default threshold adapter.");
  820. }
  821. var adaptiveTholdSpeed:Number = parseFloat(configFileXML.flarManagerSettings.@adaptiveThresholdingSpeed);
  822. if (!isNaN(adaptiveTholdSpeed)) {
  823. trace("adaptiveThresholdingSpeed attribute is deprecated as of v0.6. specify a thresholdAdapter instead, with a 'speed' attribute.");
  824. }
  825. var adaptiveTholdBias:Number = parseFloat(configFileXML.flarManagerSettings.@adaptiveThresholdingBias);
  826. if (!isNaN(adaptiveTholdBias)) {
  827. trace("adaptiveThresholdingBias attribute is deprecated as of v0.6. specify a thresholdAdapter instead, with a 'bias' attribute.");
  828. }
  829. var thresholdAdapterName:String = configFileXML.flarManagerSettings.thresholdAdapter.@className;
  830. if (thresholdAdapterName != "") {
  831. if (thresholdAdapterName.indexOf(".") == -1) {
  832. thresholdAdapterName = "com.transmote.flar.utils.threshold." + thresholdAdapterName;
  833. }
  834. try {
  835. var ThresholdAdapterClass:Class = flash.utils.getDefinitionByName(thresholdAdapterName) as Class;
  836. this.thresholdAdapter = new ThresholdAdapterClass();
  837. } catch (e:Error) {
  838. trace("error creating threshold adapter with className:"+ thresholdAdapterName +". ensure the config file specifies a fully-qualified class name, or that the class is in the com.transmote.flar.utils.threshold package. also, be sure to create a reference to the class anywhere in the project, to ensure it is compiled into the SWF.");
  839. }
  840. if (this.thresholdAdapter) {
  841. var thresholdAdapterParamsList:XMLList = configFileXML.flarManagerSettings.thresholdAdapter[0].@*;
  842. if (thresholdAdapterParamsList.length() > 1) {
  843. try {
  844. var thresholdAdapterParamsObj:Object = new Object();
  845. for (i=0; i<thresholdAdapterParamsList.length(); i++) {
  846. paramName = thresholdAdapterParamsList[i].name();
  847. if (paramName == "className") { continue; }
  848. thresholdAdapterParamsObj[paramName] = thresholdAdapterParamsList[i].toString();
  849. }
  850. this.thresholdAdapter.initFromXML(thresholdAdapterParamsObj);
  851. } catch (e:Error) {
  852. trace("error applying threshold adapter params:"+ thresholdAdapterParamsList);
  853. }
  854. }
  855. }
  856. }
  857. var sampleBlurringVal:int = parseInt(configFileXML.flarManagerSettings.@sampleBlurring);
  858. if (!isNaN(sampleBlurringVal) && sampleBlurringVal > 0) {
  859. this.sampleBlurring = sampleBlurringVal;
  860. }
  861. var markerRemovalDelayVal:int = parseInt(configFileXML.flarManagerSettings.@markerRemovalDelay);
  862. if (!isNaN(markerRemovalDelayVal) && markerRemovalDelayVal > 0) {
  863. this.markerRemovalDelay = markerRemovalDelayVal;
  864. }
  865. var minimumLabelSize:Number = parseFloat(configFileXML.flarManagerSettings.@minimumLabelSize);
  866. if (!isNaN(minimumLabelSize)) {
  867. FLARLabeling_BitmapData.minimumLabelSize = minimumLabelSize;
  868. }
  869. // camera parameters file
  870. var cameraParamsPath:String = configFileXML.cameraParamsFile.@path;
  871. // pattern list
  872. var resolutionStr:String = configFileXML.patterns.@resolution;
  873. var resolution:Number = NaN;
  874. if (resolutionStr != "") { resolution = parseFloat(resolutionStr); }
  875. var patternToBorderRatioStr:String = configFileXML.patterns.@patternToBorderRatio;
  876. var patternToBorderRatio:Number = NaN;
  877. if (patternToBorderRatioStr != "") { patternToBorderRatio = parseFloat(patternToBorderRatioStr); }
  878. var minConfidenceStr:String = configFileXML.patterns.@minConfidence;
  879. var minConfidence:Number = NaN;
  880. if (minConfidenceStr != "") { minConfidence = parseFloat(minConfidenceStr); }
  881. var patterns:Vector.<FLARPattern> = new Vector.<FLARPattern>();
  882. var patternPath:String;
  883. var patternSize:Number;
  884. for each (var pattern:XML in configFileXML.patterns.pattern) {
  885. patternSize = NaN;
  886. if (pattern.@size != "") { patternSize = parseFloat(pattern.@size); }
  887. patterns.push(new FLARPattern(pattern.@path, resolution, patternToBorderRatio, patternSize, minConfidence));
  888. }
  889. this.init(cameraParamsPath, patterns, sourceInitStruct);
  890. }
  891. private function init (cameraParamsPath:String, patterns:Vector.<FLARPattern>, sourceInitStruct:SourceInitStruct=null) :void {
  892. if (!sourceInitStruct) {
  893. sourceInitStruct = new SourceInitStruct();
  894. }
  895. this.initFlarSource(sourceInitStruct);
  896. this.loadCameraParams(cameraParamsPath);
  897. this.allPatterns = patterns;
  898. this.loadPatterns(this.allPatterns);
  899. // initialize sampleBlurFilter
  900. this.sampleBlurring = this.sampleBlurring;
  901. }
  902. private function initFlarSource (sourceInitStruct:SourceInitStruct) :void {
  903. var sourceParent:DisplayObjectContainer;
  904. var sourceAsSprite:Sprite;
  905. var sourceIndex:int;
  906. if (this._flarSource) {
  907. if (this._flarSource.inited) {
  908. // do not attempt to init if source was inited before passing into FLARManager ctor.
  909. return;
  910. }
  911. sourceAsSprite = this._flarSource as Sprite;
  912. sourceParent = sourceAsSprite.parent;
  913. }
  914. if (sourceInitStruct.useProxy) {
  915. if (sourceParent) {
  916. // if placeholder IFLARSource was already added to the display list, remove it...
  917. sourceIndex = sourceParent.getChildIndex(sourceAsSprite);
  918. sourceParent.removeChild(sourceAsSprite);
  919. }
  920. this._flarSource = new FLARProxy(sourceInitStruct.displayWidth, sourceInitStruct.displayHeight);
  921. if (sourceParent) {
  922. // ...and replace it with the new FLARLoaderSource.
  923. sourceParent.addChildAt(Sprite(this._flarSource), sourceIndex);
  924. }
  925. } else if (sourceInitStruct.loaderPath) {
  926. if (sourceParent) {
  927. // if placeholder IFLARSource was already added to the display list, remove it...
  928. sourceIndex = sourceParent.getChildIndex(sourceAsSprite);
  929. sourceParent.removeChild(sourceAsSprite);
  930. }
  931. this._flarSource = new FLARLoaderSource(
  932. sourceInitStruct.loaderPath, sourceInitStruct.sourceWidth,
  933. sourceInitStruct.sourceHeight, sourceInitStruct.downsampleRatio);
  934. if (sourceParent) {
  935. // ...and replace it with the new FLARLoaderSource.
  936. sourceParent.addChildAt(Sprite(this._flarSource), sourceIndex);
  937. }
  938. } else {
  939. FLARCameraSource(this._flarSource).addEventListener(ErrorEvent.ERROR, this.onCameraSourceError);
  940. FLARCameraSource(this._flarSource).init(
  941. sourceInitStruct.sourceWidth, sourceInitStruct.sourceHeight,
  942. sourceInitStruct.framerate, this._mirrorDisplay,
  943. sourceInitStruct.displayWidth, sourceInitStruct.displayHeight,
  944. sourceInitStruct.downsampleRatio);
  945. }
  946. }
  947. private function onCameraSourceError (evt:ErrorEvent) :void {
  948. this.deactivate();
  949. this.dispatchEvent(evt);
  950. }
  951. private function loadCameraParams (cameraParamsPath:String) :void {
  952. var loader:URLLoader = new URLLoader();
  953. loader.dataFormat = URLLoaderDataFormat.BINARY;
  954. loader.addEventListener(IOErrorEvent.IO_ERROR, this.onCameraParamsLoadError);
  955. loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onCameraParamsLoadError);
  956. loader.addEventListener(Event.COMPLETE, this.onCameraParamsLoaded);
  957. loader.load(new URLRequest(cameraParamsPath));
  958. }
  959. private function onCameraParamsLoadError (evt:Event) :void {
  960. var errorText:String = "Camera params load error.";
  961. if (evt is IOErrorEvent) {
  962. errorText = IOErrorEvent(evt).text;
  963. } else if (evt is SecurityErrorEvent) {
  964. errorText = SecurityErrorEvent(evt).text;
  965. }
  966. this.onCameraParamsLoaded(evt, new Error(errorText));
  967. }
  968. private function onCameraParamsLoaded (evt:Event, error:Error=null) :void {
  969. var loader:URLLoader = evt.target as URLLoader;
  970. loader.removeEventListener(IOErrorEvent.IO_ERROR, this.onCameraParamsLoadError);
  971. loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onCameraParamsLoadError);
  972. loader.removeEventListener(Event.COMPLETE, this.onCameraParamsLoaded);
  973. if (error) { throw error; }
  974. this._cameraParams = new FLARParam();
  975. this._cameraParams.loadARParam(ByteArray(loader.data));
  976. var sourceSize:Rectangle = this.flarSource.sourceSize;
  977. this._cameraParams.changeScreenSize(sourceSize.width, sourceSize.height);
  978. this.bCameraParamsLoaded = true;
  979. this.checkForInitComplete();
  980. }
  981. private function loadPatterns (patterns:Vector.<FLARPattern>) :void {
  982. this.patternLoader = new FLARPatternLoader();
  983. this.patternLoader.addEventListener(Event.INIT, this.onPatternsLoaded);
  984. this.patternLoader.loadPatterns(patterns);
  985. }
  986. private function onPatternsLoaded (evt:Event) :void {
  987. this.patternLoader.removeEventListener(Event.INIT, this.onPatternsLoaded);
  988. this.bPatternsLoaded = true;
  989. this.checkForInitComplete();
  990. }
  991. private function checkForInitComplete () :void {
  992. if (!this.bCameraParamsLoaded || !this.bPatternsLoaded || !this._flarSource) { return; }
  993. if (this.patternLoader.loadedPatterns.length == 0) {
  994. throw new Error("no markers successfully loaded.");
  995. }
  996. try {
  997. this.flarRaster = new FLARRgbRaster_BitmapData(this.flarSource.source);
  998. } catch (e:Error) {
  999. // this.flarSource not yet fully initialized
  1000. this.flarRaster = null;
  1001. }
  1002. this.markerDetector = new FLARMultiMarkerDetector(this._cameraParams, this.patternLoader.loadedPatterns, this.patternLoader.unscaledMarkerWidths, this.patternLoader.loadedPatterns.length);
  1003. //this.markerDetector.setContinueMode(true);
  1004. if (this.thresholdSourceDisplay) {
  1005. // if this.thresholdSourceDisplay was set to true before initialization of
  1006. // this.flarSource and this.markerDetector, reset it.
  1007. this.thresholdSourceDisplay = true;
  1008. }
  1009. if (!this.smoother) {
  1010. this.smoother = new FLARMatrixSmoother_Average();
  1011. }
  1012. if (!this.thresholdAdapter) {
  1013. this.thresholdAdapter = new DrunkWalkThresholdAdapter();
  1014. }
  1015. this.bInited = true;
  1016. this.activate();
  1017. this.dispatchEvent(new Event(Event.INIT));
  1018. }
  1019. //-----</INITIALIZATION>---------------------------//
  1020. }
  1021. }
  1022. internal class SourceInitStruct {
  1023. internal var sourceWidth:int = 640;
  1024. internal var sourceHeight:int = 480;
  1025. internal var displayWidth:int = 640;
  1026. internal var displayHeight:int = 480;
  1027. internal var framerate:Number = 30;
  1028. internal var downsampleRatio:Number = 0.5;
  1029. internal var useProxy:Boolean = false;
  1030. internal var loaderPath:String = "";
  1031. public function SourceInitStruct () {}
  1032. }