Augmented Reality Mixed Reality Virtual Reality
A new approach to 3-D holographic displays greatly improves the image quality
AS3 Super Loader Part 2
This post is a continuation of the Action Script 3 Super Loader, hospital find though this tip could have many adaptations besides the example below.
Many may already know that when you go to the Publish Settings/ HTML window, page there is a drop-down that allows for the choice of HTML templates to use with your .swf. When Flash publishes the HTML page along with the .swf, it dynamically creates the new HTML file that will host your Flash movie, with the correct width, height, file name, background color of the .swf in the source code. Many developers use this HTML page to copy the embed code into another file. Some people ignore this feature all together and use Dreamweaver to produce the code or have a custom HTML template that they modify manually.
There are other options in this drop-down that include things like Flash version checking, scorm support, and SSL encryption. But the reality is, most of us would not use these files in a website or to show a client without at least a little modification. That is why we all probably have a few HTML templates of our own laying around.
Why not take those templates and make Flash HTML Templates, which is super easy. My default template has some custom css styles, javascript functions and centers the .swf on the page. I can use this HTML file to show development progress to a client.
I also have some custom scorm templates that work with a few different tracking systems. A lot of us use swfObject, you can even build a template that produces the correct code for swfObject on export. This may not be a huge time savings, but it is part of a smoother workflow.
This hint is about hooking up our Super Loader to an HTML template, but it should be enough information to build any kind of template.
First off, you should backup your existing HTML template files in case of any errors and more importantly, back up your custom templates in case a Flash update replaces them or a system crash. Plus you may want to share you templates or use them to standardize the workflow of your development team.
The templates are located in User Folder/Library/Application Support/Adobe/Flash CS3/en/Configuration/HTML/ on the mac, or C:Program FilesAdobeAdobe Flash CS3enConfiguration on the PC.
Inside the default.html file, you will see the script for embedding the .swf using AC_RunActiveContent. This script shows the best description of what most of the variables are.
Other Variables that are not well defined below:
$TT = the name that will show up in the drop down menu.
$DX, $DS, and $DF = flash version detection and the AC_RunActiveContent generation.
$CS = metedata tag
$PO = param tags for width, height, quality and color.
The rest is just HTML, so go crazy.
Modifying the Super Loader Stage class:
The first thing we need to do is modify the Super Stage class to allow for a dynamic source file, with a variable check.
class original source here.
[ad#content_banner]
package com.HDI.stage {
/*import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageDisplayState;
import flash.events.MouseEvent;
import flash.geom.Rectangle;*/
import flash.display.Stage;
import flash.display.StageDisplayState;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.display.MovieClip;
public class SuperStage extends MovieClip {
//External Variables:
var fps:Number = 30;
/* remove the variable definition from swfURL*/
var swfURL:String;
var ldrURL:String = "loaderbar.swf";
//Loader Variables:
var loadComplete:Boolean = false;
var loadPerc:Number;
var loaderCnt:Number = 0;
//Internal Objects:
var mainMovie:Object;
var mainLdr:Object;
var mainContainer:MovieClip;
var loaderMC:MovieClip;
public function SuperStage():void{
init();
}
private function init():void{
/* Add variable check here and use a default swf name if swfURL does not exist.*/
if(loaderInfo.parameters.swfURL){
swfURL = loaderInfo.parameters.swfURL;
}
else{
swfURL = "sample.swf";
}
//Set all the stage properties onload
stage.showDefaultContextMenu = false;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//load the main container and the loader container
/*
this is not manditory and can make things more complex,
but so that the loader always stays on top, I add these to MovieClips
then load everything else inside these clips.
Load the loaderMC second so that it remains on top.
*/
mainContainer = new MovieClip();
addChild(mainContainer);
loaderMC = new MovieClip();
addChild(loaderMC);
//setup stage init incase I need it later.
loaderInfo.addEventListener(Event.INIT,initStage);
//start to load the loader bar.
loadObject(loaderMC,ldrURL,null);
stop();
}
function initStage(ev:Event):void{
//stage.stageWidth = thisWidth;
//stage.stageHeight = thisHeight;
}
//main loader method
function loadObject(targ:Object,path:String,mon:Object):void{
var ldr:Loader = new Loader();
var ldrReq:URLRequest = new URLRequest(path);
ldr.load(ldrReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, ldrFin);
ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, ldrProgress);
ldr.name = "ldr" + loaderCnt;
targ.addChild(ldr);
loaderCnt ++;
}
//finish loading. first two items loaded will be ldr0(loader bar) and ldr1(main content)
function ldrFin(ev:Event):void{
if(ev.target.loader.name == "ldr0"){
mainLdr = ev.target.content;
mainLdr.loadStat = true;
mainLdr.x = (stage.stageWidth/2)-(mainLdr.width/2);
mainLdr.y = (stage.stageHeight/2)-(mainLdr.height/2);
loadObject(mainContainer,swfURL,mainLdr);
}
else if(ev.target.loader.name == "ldr1"){
mainMovie = ev.target.content;
stage.frameRate = ev.target.frameRate;
}
}
//progress handler, sends loading info to loader bar.
function ldrProgress(ev:ProgressEvent):void{
if(mainLdr){
mainLdr.ldrMon(ev.bytesLoaded/ev.bytesTotal);
}
}
}
}
The rest happens in the HTML Template:
The new template is a modified copy of the default template.
It will set the stage swf as the source, then we will use flashVars to load in the current project name that will be used by the loader to display our current file.
$TTSuper Loader
$DXDefaultDetection.html
$DS
Display Adobe Flash Movies in HTML files updated for Active Content. NOTE: Publishing this template also creates AC_RunActiveContent.js in your HTML output folder which must be uploaded with the HTML.
$DF
$CS
$TI
AC_FL_RunContent = 0;
http://AC_RunActiveContent.js
body{
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
font-family: Arial;
font-size: 11px;
}
center{
margin: 10% 0px 0px 0px;
}
$MU
$MT
if (AC_FL_RunContent == 0) {
alert("This page requires AC_RunActiveContent.js.");
} else {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=$FV,$JR,$NR,0',
'width', '$WI',
'height', '$HE',
'src', 'mainFlash',
'quality', '$QU',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', '$HA',
'play', '$PL',
'loop', '$LO',
'scale', '$SC',
'wmode', '$WM',
'devicefont', '$DE',
'id', 'mainFlash',
'bgcolor', '$BG',
'name', 'mainFlash',
'menu', '$ME',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', '$MO',
'salign', '$SA' ,
'FlashVars', 'swfURL=$TI' + '.swf'
); //end AC code
}
©2008 taterboy, Inc. All Rights Reserved
Pretty Simple.
source
UPDATE
Updated the following code in “com/HDI/stage/SuperStage.as” so that the Loader will actually work with FlashVars. Also updated “FlashVars” in the HTML template code to have a capital “F”. The source files have been updated as well.
if(loaderInfo.parameters.swfURL){
swfURL = loaderInfo.parameters.swfURL;
}
else{
swfURL = "sample.swf";
}
I really enjoy coding in AS3, find but one of the things I dislike the most is the fact that when building movieclips as Classes, capsule you have to export to Action Script or place all your movieclips on the stage somewhere. I think the latter is not very flexible. I understand why it has to be done; I just don’t like it. The problem with exporting everything to the Action Script is that it loads that MovieClip on the first frame, and loaders that are normally placed on the first frame will not show up or function until the first frame is loaded. This first frame now contains all our content that we have exported to Action Script which really defeats the purpose of a loader. That is why you will see a blank white box for a few seconds or longer before the loader shows up. The best way to fix this is to build a loader swf to load our current project swf into.Â
But you know what would be even cooler? A Super Loader!
This super loader could be so smart, that we could code it once, then use it as a loader for every project we do in the future. It will load in any-size swf at any frame-rate, and to get even sicker, let’s make the loader bar or display animation external so that we can make many different loaders for different projects and have them work with this super loader as well.Â
So welcome to Super Loader and Super Stage.
A few of the features we will be using to pull this off are the new Stage frameRate, Loader and ProgressEvent classes.

Step 1: Host SWF and SuperStage Class.
The host file is a blank fla that points to our SuperStage Class. We do not care about what size it is, what color the background is or the frame rate. We will be able to control all that later with our SuperStage Class.
The Code:
Open the package and import all the needed Classes. I am organizing these classes more like I would if I were working on a large project. Hence the com.HDI.stage. You could remove this and place the .as file in the same directory as the .fla if that is easier.
package com.HDI.stage {
/*import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageDisplayState;
import flash.events.MouseEvent;
import flash.geom.Rectangle;*/
import flash.display.Stage;
import flash.display.StageDisplayState;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.display.MovieClip;
import com.HDI.events.loaderEvent;
public class SuperStage extends MovieClip {
//External Variables:
//var thisWidth:Number = 800;
//var thisHeight:Number = 600;
var fps:Number = 30;
var swfURL:String = "imgViewer.swf";
var ldrURL:String = "loaderbar.swf";
//Loader Variables:
var loadComplete:Boolean = false;
var loadPerc:Number;
var loaderCnt:Number = 0;
//Internal Objects:
var mainMovie:Object;
var mainLdr:Object;
var mainContainer:MovieClip;
var loaderMC:MovieClip;
public function SuperStage():void{
init();
}
private function init():void{
//Set all the stage properties onload
stage.showDefaultContextMenu = false;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//load the main container and the loader container
/*
this is not manditory and can make things more complex,
but so that the loader always stays on top, I add these to MovieClips
then load everything else inside these clips.
Load the loaderMC second so that it remains on top.
*/
mainContainer = new MovieClip();
addChild(mainContainer);
loaderMC = new MovieClip();
addChild(loaderMC);
//setup stage init incase I need it later.
loaderInfo.addEventListener(Event.INIT,initStage);
//start to load the loader bar.
loadObject(loaderMC,ldrURL,null,ldrFin);
stop();
addEventListener(loaderEvent.LOAD,loadNewObject);
}
function initStage(ev:Event):void{
//stage.stageWidth = thisWidth;
//stage.stageHeight = thisHeight;
}
}
}
[ad#content_banner]
It is supposed to be a best practice to not have a lot of code in your class method. I use an init function to set everything up. This is a very similar practice to flex programming when you call an init function on creationComplete. Another advantage is that we can call init(), if it is public, from an external source or to reload/reset the class.
In this init function we will set up all of our stage properties. When everything loads we want to have a loader bar that appears in the center of the screen while the main content is loading. Being a super loader, it will need to appear on top of everything, and we can use it later to load in other content. When Flash loads new content, it will load new stuff on top of the old stuff. So to make sure our loader stays on top without swapping depths all the time, we will add a main content MovieClip to the stage first, then add our loader MovieClip. Now load all the content into the main content clip which will always exist below the loader MovieClip.
Step 2: Main Loader Engine
Using the Object Loader method we can load in our loader bar, main content, and any other swfs or images in the future.Â
function loadNewObject(ev:loaderEvent):void{
loadObject(ev.ldrTarget,ev.ldrURL,mainLdr,ev.ldrFunction);
}
//main loader method
function loadObject(targ:Object,path:String,mon:Object,funFunction:Function):void{
var ldr:Loader = new Loader();
var ldrReq:URLRequest = new URLRequest(path);
ldr.load(ldrReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, funFunction);
ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, ldrProgress);
ldr.name = "ldr" + loaderCnt;
targ.addChild(ldr);
loaderCnt ++;
}
//finish loading. first two items loaded will be ldr0(loader bar) and ldr1(main content)
function ldrFin(ev:Event):void{
if(ev.target.loader.name == "ldr0"){
mainLdr = ev.target.content;
mainLdr.loadStat = true;
mainLdr.x = (stage.stageWidth/2)-(mainLdr.width/2);
mainLdr.y = (stage.stageHeight/2)-(mainLdr.height/2);
loadObject(mainContainer,swfURL,mainLdr,ldrFin);
}
else if(ev.target.loader.name == "ldr1"){
mainMovie = ev.target.content;
stage.frameRate = ev.target.frameRate;
}
}
//progress handler, sends loading info to loader bar.
function ldrProgress(ev:ProgressEvent):void{
if(mainLdr){
mainLdr.ldrMon(ev.bytesLoaded/ev.bytesTotal);
}
}
Note:
The targeting of objects after they are loaded can be a little tricky. There is the main movie clip as the parent, the loader object, then the loader content. If you are managing a large amount of MovieClips then it may be a good idea to add each object to an array as they are loaded.
The frameRate is set when the main content loads. The width and height and background colors are established by the html host file which makes this loader pretty flexible. Right now you have to change the urls to the loader and swf, which isn’t so super, but they can be moved out into the html embed code as variables or we can change the names of our files to be more generic. My next post will go into more depth about implementing this into a workflow and how to automatically configuring the super loader on publish. So come back soon.
In the meantime, we can work on our loader bar.
You can see in the following code that there is a loader bar and monitoring code for the content being loaded. We also set the loaders x and y position to be dead center of our stage dynamically depending on the size of the main content.
package com.HDI.loaders {
import flash.display.Sprite;
import flash.display.MovieClip;
public class LdrBar extends MovieClip{
//load status. I may need this later
public var loadStat:Boolean;
public function LdrBar():void{
stop();
init();
}
public function init():void{
//On init, loader animation and bar size is reset.
//The best part of use the init function instead of the
//class method, is that I can call this anytime to reset the loader.
ani.stop();
bar.scaleX = 0.01;
}
public function ldrMon(perc:Number):void{
//main loader animation control.
//this method is called from the host using the progress event.
//as the progress changes, the loader becomes visible and the animation plays.
if(perc < 1){
visible = true;
bar.scaleX = perc;
ani.play();
}
else{
// when progress stops, loader becomes invisible and animation stops.
ani.stop();
visible =false;
}
}
}
}
Step 3: Loader Bar Animation and Image Viewer.
The Super part of this loader is the fact that you can create new loader graphics, animation, and progress indicators; and load those in without changing any code in our super stage. The host file only cares about loading in something; it can even be an image. Then the loader will receive and update every time the progress changes. It would be a pretty boring loader if it were an image, but the point has been made that it could be.
This loader acts like a loader bar with an animation effect that is visible when progress is updated and invisible when there is no progress. I have included a simple image viewer to show how to use the same loader for everything that is loaded into our main movie. If you have a fast connection, then you may not see much and will have to take my word for it, It looks awesome! And how do we call the loader feature from our main movie? Using a dispatchEvent and a custom event of course, you can read more about that here if you haven’t already.
I hope you enjoyed this tutorial and stay tuned for the next post which will take these super components and integrate them into a workflow that can only be described as, well, “Super”.
[kml_flashembed movie=”/blog/flash/superLoader/mainFlash.swf” height=”280″ width=”472″ fversion=”9″ /]
UPDATE:
Someone asked how to remove loaded items. The image viewer example above just stacks one image on top of another. Â If you have swfs with music and/or animation this can cause problems. If you are using the same MovieClip as a holder for all of your loaded items, then place a new MovieClip as a child of the holder and load all items in the child, that way you can remove the childClip before loading new objects.
This is a modification that can beadded to the imgViewer.fla in the source files.
function mouseHandler(ev:MouseEvent):void{
imgLoader.visible = false;
instructions.visible = false;
//-- new code
if(imgLoader.numChildren > 0){
imgLoader.removeChild(imgLoader.getChildByName("imgHolder1"));
}
var tempIMG:MovieClip = new MovieClip();
tempIMG.name = "imgHolder1";
imgLoader.addChild(tempIMG);
// -- end new code
dispatchEvent(new loaderEvent(loaderEvent.LOAD,tempIMG,"images/3d_sketch.jpg",imgLoaded));
// replace all instances of "imgLoader" with "tempIMG" in the event dispatchers.
}
***Cleaner way is to use the childMonitor Class and the pullAll() method to remove all items before loading a new item.
import com.hdi.util.ChildMonitor;
var cmt:ChildMonitor = new ChildMonitor(imgLoader);
function mouseHandler(ev:MouseEvent):void{
imgLoader.visible = false;
instructions.visible = false;
//-- new code
if(cmt.childList.length > 1){
cmt.pullAll();
}
// -- end new code
dispatchEvent(new loaderEvent(loaderEvent.LOAD,imgLoader,"images/3d_sketch.jpg",imgLoaded));
}
[kml_flashembed fversion=”8.0.0″ movie=”http://www.taterboy.com/blog/flash/countDown.swf” targetclass=”flashmovie” publishmethod=”static” width=”300″ height=”30″ wmode=”transparent” fvars=”tdate=2012, sale 12, no rx 21, dosage 19&hex=154e6d&blink=true”]
The Settings:
The first thing in our code is deciding if our timer is going to blink every second or not. Blinking gives the impressing of time passing and is easier to notice then just one or two numbers incrementing. Just set “blinking” to true or false
/** timer settings ****************************************************************/
var blinking:Boolean = true; // allow timers to blink every second
var osecs:Number = 0; //used to enable flashing
The Dates:
The countdown timer takes a future date and figures out how many days, hours, mins, and seconds from now until that date arrives. The next thing we need to do is enter in our future date for the timer to count to. To make things easy, the date is broken into year, month, day, hour, min, sec, and millisecond.
/** date settings ****************************************************************/
// set the target date
var timeToYear:Number = 2012; // full year 2010
var timeToMonth:Number = 12; // month 1 - 12
var timeToDate:Number = 21; // date 1 - 31 depending on month
var timeToHour:Number = 0; // hour 0 - 23
var timeToMin:Number = 0; // min 0 - 59
var timeToSec:Number = 0; // sec 0 - 59
var timeToMilSec:Number = 0; // milliseconds 0 - 999
Dealing with Time-Zones:
Most timers need to sync across time-zones, this can be a pain, complicated by day-light savings. We only need to set a time-zone offset if our timer’s target date based on a particular location and we wanted people from other locals to countdown at the exact same time. Say we have an event occurring in New York City, we want everyone in the world to know the exact time the event is going to occur. We will need to set “timeZone” to -5 for eastern standard time unless the date falls in the summer time, then we should use -4 for eastern daylight time.
var timeZone:Number = 0; // time-zone offset - set this if the target time is time-zone based.
The Target Date vs. Todays Date:
After all the settings are made, it is time to setup our current date and compare it to a future date. Since we do not want our countdown timer to count if our target date has past, then we need to check for that. If the target date is not in the future we will reset all the values to 0 and stop the timer.
// gets todays date as Universal Time
var today:Date = new Date(Date.UTC());
// sets the target date as Universal Time
var targDate:Date = new Date(Date.UTC(timeToYear,timeToMonth - 1,timeToDate,timeToHour,timeToMin,timeToSec,timeToMilSec));
// check to make sure target date is in the future
if(targDate < today){
targDate = today;
}
The Magic:
Here is where all the magic happens. We create a new date on every frame, add the time-zone offset then compare it to the target date. The difference of the two dates is what we use to fill in the countdown clock. In this timer we are counting down by days, but we could modify it to count down years and months as well. When we compare dates, the value that is returned is in milliseconds, so we have to convert that very large number into our desired time increment.
var days:Number = ((((target date - current date) / 1000)/60)/60)/24;
This line of code takes the target date and subtracts the current date which returns the difference in milliseconds. To convert the difference into our base time we need to divide.
[ad#content_banner]
Here are some samples for converting different time increments from milliseconds to create out base time increment.
milliseconds
target date - current date
seconds
(target date - current date) / 1000
minutes
((target date - current date) / 1000)/60
hours
(((target date - current date) / 1000)/60)/60
days
((((target date - current date) / 1000)/60)/60)/24;
months (A)
getting this value is more complex, here is a rough, quick value.
((((((target date - current date) / 1000)/60)/60)/24)/365)*12
months (B)
for more exact values, we will need to get the difference in months using Date.getMonth().
1. get the years
var yearsTill:Number = ((((((target date - current date) / 1000)/60)/60)/24)/365);
2. get the difference in months
var monthsTill:Number = target date - current date .getMonth() - today.getMonth();
3. check if the amount of months is a negative number
if(monthsTill < 0){
mulitply years by 12, then add the amount of months till the end of the year.
trace((Math.floor(yearsTill) * 12) + (11 + monthsTill));
}
else{
multiply years by 12, plus the difference in months.
trace((Math.floor(yearsTill) * 12) + (monthsTill));
}
years
(((((target date - current date) / 1000)/60)/60)/24)/365
After we get a value for our base increment, we round it down (Math.floor()) and take the remainder to create all of the smaller increments. In the line below, we take the total days and subtract the days rounded down. This returns a percent of a day so we need to multiply it by 24 to get the total amount of hours. We will repeat this process, until we have reduced the remaining value into all of the smaller time increments.
hours = (total days - Math.floor(total days))*24;
minutes = (total hours - Math.floor(total hours))*60;
seconds = Math.floor((total minutes - Math.floor(total minutes))*60);
/** timer animation magic ********************************************************/
// start on Enterframe event and handler only if target date is in the future
if(targDate > today){
this.onEnterFrame = function(){
// if target date is not in the future, stop counter.
var dateArr:Date = new Date(Date.UTC());
if(dateArr >= targDate){
days.dyt.text = "000";
hrs.hrt.text = "00";
mins.mnt.text = "00";
secs.sct.text = "00";
delete this.onEnterFrame;
return;
}
// set the hours and adjust if there is time-zone offset
dateArr.setHours(dateArr.getHours() + timeZone);
// DAYS - get the time difference in days
var daysData:Number = ((((targDate - dateArr) / 1000)/60)/60)/24;
// round down days
var daysTill:Number = Math.floor(daysData);
// HOURS - get the difference in hours
var hoursData:Number = (daysData - Math.floor(daysData))*24;
//round down hours
var hoursTill:Number = Math.floor(hoursData);
// MINUTES - get the difference in minutes
var minsData:Number = (hoursData - Math.floor(hoursData))*60;
// round down minutes
var minsTill:Number = Math.floor(minsData);
// SECONDS - get difference in seconds
var secsTill:Number = Math.floor((minsData - Math.floor(minsData))*60);
// do timer blinking every second (if enabled)
var blinkThis:Boolean = false;
if(secsTill != osecs){
if(blinking){
blinkThis = true;
}
}
osecs = secsTill;
// format days till number
if(daysTill > 99){
days.dyt.text = daysTill;
}
else if(daysTill > 9){
days.dyt.text = "0" + daysTill;
}
else{
days.dyt.text = "00" + daysTill;
}
// add timer info to the correct text fields
if(!blinkThis){
hoursTill < 10 ? hrs.hrt.text = "0" + hoursTill: hrs.hrt.text = hoursTill;
minsTill < 10 ? mins.mnt.text = "0" + minsTill: mins.mnt.text = minsTill;
secsTill < 10 ? secs.sct.text = "0" + secsTill: secs.sct.text = secsTill;
}
else{
// handle blinking (if enabled)
days.dyt.text = "";
hrs.hrt.text = "";
mins.mnt.text = "";
secs.sct.text = "";
blinkThis = false;
}
}
}
You can download a source FLA here.
In an earlier post, I created a timer that you can add to your site or blog and configure using flashVars in the HTML object/embed code. Flash AS2 Count Down Timer
Flash developers have been using filters on MovieClips since Flash 8. Filters in Flex it is not as easy as using Flashes Filters property panel, viagra order but they are available. Many samples show how to create filters using pure ActionScript, medications but these samples use good old mxml and I think are a lot easier to use. Filters can be used on most DisplayObjects and dynamic text.
There are 6 other filters that are not contained in this demo:
- ColorMatrixFilter
- ConvolutionFilter
- DisplacementMapFilter
- EffectTargetFilter
- GradientBevelFilter
- GradientGlowFilter
[ad#content_banner]
[kml_flashembed movie="http://www.taterboy.com/blog/flash/flexFilters.swf" height="240" width="500" /]
Using visualization technology, cheapest visitors to the British Museum can reveal the murder of the mummified Geberlein Man, stomach 5,500 years ago.
Powered by WPeMatico
With the addition of holographic diffusers or frosted glasses to wavefront modulators, what is ed researchers offer a simple and practical solution to significantly enhance the performance of 3D dynamic holographic displays by 2,600 times.
Powered by WPeMatico