{"id":536,"date":"2011-02-22T03:44:23","date_gmt":"2011-02-22T07:44:23","guid":{"rendered":"http:\/\/www.searchenginegenie.com\/web-design-blog\/?p=536"},"modified":"2011-02-22T06:07:49","modified_gmt":"2011-02-22T10:07:49","slug":"3d-particles-rotation-in-flash","status":"publish","type":"post","link":"https:\/\/www.searchenginegenie.com\/web-design-blog\/3d-particles-rotation-in-flash\/","title":{"rendered":"3D Particles rotation in flash"},"content":{"rendered":"<p><object id=\"test\" classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" width=\"550\" height=\"400\" codebase=\"http:\/\/download.macromedia.com\/pub\/shockwave\/cabs\/flash\/swflash.cab#version=6,0,40,0\"><param name=\"src\" value=\"http:\/\/www.searchenginegenie.com\/web-design-blog\/wp-content\/uploads\/2011\/02\/3D-particles-twisting-effect-flash.swf\" \/><param name=\"name\" value=\"test1\" \/><embed id=\"test\" type=\"application\/x-shockwave-flash\" width=\"550\" height=\"400\" src=\"http:\/\/www.searchenginegenie.com\/web-design-blog\/wp-content\/uploads\/2011\/02\/3D-particles-twisting-effect-flash.swf\" name=\"test1\"><\/embed><\/object><\/p>\n<p>1. Open a new document and set background color as black.<\/p>\n<p>2. Select Layer-1, Keyframe 1. Press F9 to write the following action script. I have explained the code in the comments.<br \/>\nimport fl.motion.easing.Quartic;<br \/>\nimport fl.motion.easing.Bounce;<br \/>\nimport fl.motion.Animator3D;<br \/>\nimport main.submain.loaders.*;<br \/>\nimport main.submain.bitmapUtilities.PictureAtomizer;<br \/>\nimport main.submain.objects.Particle3D;<br \/>\nimport main.submain.geom3D.*;<br \/>\nimport main.submain.display.*;<br \/>\nvar picURLString:Array; \/\/ var is a variables, picURLString is a type and array is an atrribute<br \/>\nvar picLoader:PictureLoader;<br \/>\nvar pic:Array;<br \/>\nvar atomizer:PictureAtomizer;<br \/>\nvar particles:Array;<br \/>\nvar blur:BlurFilter;<br \/>\nvar darken:ColorTransform;<br \/>\nvar board:RotatingParticleBoard;<br \/>\nvar boardRect:Rectangle;<br \/>\nvar filterPoint:Point;<br \/>\nvar p:Particle3D;<br \/>\nvar param:Number;<\/p>\n<p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\ninit(); \/\/ function name<br \/>\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\nfunction init():void {<br \/>\npicURLString= [&#8220;image\/violet.jpg&#8221;];  \/\/path of image<br \/>\npicLoader = new PictureLoader();<br \/>\nboard = new RotatingParticleBoard(500,340,true, 0x00000000, 500); \/\/set the width and height of rectangle box<br \/>\nboard.setDepthDarken(-10,-80,1.5);  \/\/ brightens and darken the image<br \/>\nboard.makeFrame(1,0xffffff,5);  \/\/ stroke and color of rectangle box<br \/>\nboard.holder.x = stage.stageWidth\/2 &#8211; board.width\/2;  \/\/ position of rectangle box in x-axis<br \/>\nboard.holder.y = stage.stageHeight\/2 &#8211; board.height\/2;  \/\/position of rectangle box in y-axis<br \/>\n\/\/set the starting rotation:<br \/>\nboard.currentQ = new Quaternion(Math.cos(Math.PI\/12), Math.sin(Math.PI\/2)\/Math.sqrt(2),0,-Math.sin(Math.PI\/5)\/Math.sqrt(2));<br \/>\n\/\/set the automatic rotation to use while mouse is not dragging:<br \/>\nboard.autoQuaternion = new Quaternion(Math.cos(Math.PI\/300),0,Math.sin(Math.PI\/300),0);<br \/>\nblur = new BlurFilter(50,50);<br \/>\ndarken = new ColorTransform(500,1,1,0.9); \/\/ RGB colors and 0.9 gives the smoke effect<br \/>\nboardRect = new Rectangle(0,0,board.width,board.height);<br \/>\nfilterPoint = new Point(0,0);<br \/>\n\/\/add following code to see arcball silhouette:<br \/>\n\/*<br \/>\nvar ballOutline:Shape = new Shape();<br \/>\nballOutline.graphics.lineStyle(1,0&#215;888888);<br \/>\nballOutline.graphics.drawCircle(0,0,board.arcballRad);<br \/>\nballOutline.x = board.width\/2;<br \/>\nballOutline.y = board.height\/2;<br \/>\nboard.holder.addChild(ballOutline);<br \/>\n*\/<br \/>\npicLoader.addEventListener(PictureLoader.ALL_PICS_LOADED, createParticles);<br \/>\npicLoader.loadPics(picURLString);<br \/>\n}<br \/>\nfunction createTextLabels():void {<br \/>\nvar box:TextField = new TextField();<br \/>\nvar format:TextFormat = new TextFormat(&#8220;Times New Roman&#8221;,16,0xffffff);<br \/>\nbox.defaultTextFormat = format;<br \/>\nbox.text = String(particles.length)+ &#8221; particles.&#8221;;<br \/>\nbox.x = board.holder.x+1;<br \/>\nbox.y = board.holder.y+board.height+5;<br \/>\nstage.addChild(box);<br \/>\nvar box2:TextField = new TextField();<br \/>\nbox2.defaultTextFormat = format;<br \/>\nbox2.multiline = false;<br \/>\nbox2.autoSize = TextFieldAutoSize.RIGHT;<br \/>\nbox2.x = board.holder.x+board.width-5-box2.width;<br \/>\nbox2.y = board.holder.y+board.height+5;<br \/>\nstage.addChild(box2);<br \/>\nvar box3:TextField = new TextField();<br \/>\nbox3.defaultTextFormat = format;<br \/>\nbox3.multiline = false;<br \/>\nbox3.autoSize = TextFieldAutoSize.CENTER;<br \/>\nbox3.text = &#8220;Drag the mouse to rotate&#8221;;<br \/>\nbox3.x = board.holder.x+board.width\/2-box3.width\/2;<br \/>\nbox3.y = board.holder.y-25;<br \/>\nstage.addChild(box3);<br \/>\n}<br \/>\nfunction createParticles(evt:Event):void {<br \/>\npic = picLoader.picArray;<br \/>\npicLoader.removeEventListener(PictureLoader.ALL_PICS_LOADED, createParticles);<br \/>\natomizer = new PictureAtomizer();<br \/>\natomizer.sampling = 1;<br \/>\natomizer.spread = 1.50;<br \/>\natomizer.sampleFuzzX = 0;<br \/>\natomizer.sampleFuzzY = 0;<br \/>\natomizer.originX = Math.floor(pic[0].width\/2);<br \/>\natomizer.originY = Math.floor(pic[0].height\/2);<br \/>\natomizer.addEventListener(PictureAtomizer.PARTICLES_CREATED, go);<br \/>\natomizer.createParticles(pic[0]);<br \/>\n}<br \/>\nfunction go(evt:Event):void {<br \/>\nparticles = atomizer.particleArray;<br \/>\natomizer.setPositionsByPic(0,0,0); \/\/center position<br \/>\nstage.addChild(board.holder);<br \/>\ncreateTextLabels();<br \/>\nstage.addEventListener(Event.ENTER_FRAME, onEnter);<br \/>\n}<br \/>\nfunction onEnter(evt:Event):void {<br \/>\n\/\/Viewpoint-independent changes to particle positions. Here we present an example of each particle oscillating in the z direction, with amplitude related to the luminance of the particle. \/\/<br \/>\nparam = 0.65*Math.min(1.75,Math.max(0,(1-Math.cos(getTimer()*.0003)-0.25*Math.cos(getTimer()*.0006))));<br \/>\nfor (var i:Number = 0; i&lt;= particles.length &#8211; 1; i++) {<br \/>\np = particles[i];<br \/>\np.z = param*(p.lum-128);<br \/>\n}<br \/>\n\/\/apply Filters to effect fade-out of old pixels<br \/>\nboard.bitmapData.applyFilter(board.bitmapData, boardRect, filterPoint, blur);<br \/>\nboard.bitmapData.colorTransform(boardRect,darken);<br \/>\n\/\/draw particles<br \/>\nboard.drawParticles(particles);<br \/>\n}<\/p>\n<p>3. Here the path of folder name is very important. So give the proper name to your folder and files and give the same path name in actionscript too. Keep your fla file in separate folder name it as your wish like \u201c3Dparticles\u201d and inside this folder create one folder in the name of \u201cImage\u201d. Place all your required pictures in this folder.<\/p>\n<p>4. Create one folder inside the \u201c3Dparticles\u201d folder in the name of \u201cmain\u201d. Again create one \u201csubmain\u201d folder within the \u201cmain\u201d.<\/p>\n<p>5. it\u2019s time to create five folders inside the \u201csubmain\u201d. Name it as bitmapUtilities, display, geom3D, loaders, and objects.<\/p>\n<p>6. Open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cPictureAtomizer\u201d in \u201cbitmapUtilities\u201d:<\/p>\n<p>package main.submain.bitmapUtilities {<br \/>\nimport flash.display.*;<br \/>\nimport flash.events.*;<br \/>\nimport main.submain.geom3D.*;<br \/>\nimport main.submain.objects.Particle3D;<br \/>\npublic class PictureAtomizer extends EventDispatcher {<br \/>\npublic static const PARTICLES_CREATED:String=&#8221;particlesCreated&#8221;;<br \/>\npublic var pic:Bitmap;<br \/>\npublic var sampling:Number;<br \/>\npublic var spread:Number;<br \/>\npublic var originX:Number;<br \/>\npublic var originY:Number;<br \/>\npublic var sampleFuzzX:Number;<br \/>\npublic var sampleFuzzY:Number;<br \/>\nprivate var _particleArray:Array;<br \/>\npublic function PictureAtomizer(inputSampling=1, inputSpread=1, inputOriginX=0, inputOriginY=0, inputFuzzX=0, inputFuzzY=0):void {<br \/>\nthis.sampling = inputSampling;<br \/>\nthis.spread = inputSpread;<br \/>\nthis.originX = inputOriginX;<br \/>\nthis.originY = inputOriginY;<br \/>\nthis.sampleFuzzX = inputFuzzX;<br \/>\nthis.sampleFuzzY = inputFuzzY;<br \/>\nthis._particleArray = [];<br \/>\n}<br \/>\npublic function createParticles(inputPic:Bitmap):void {<br \/>\nvar c:uint;<br \/>\nvar m:Number;<br \/>\nvar num:Number = 0;<br \/>\nvar x0:Number;<br \/>\nvar y0:Number;<br \/>\nthis.pic = inputPic;<br \/>\n\/\/separate picture pixels into layers<br \/>\nfor (var i:Number=0; i&lt;=pic.width-1; i = i + sampling) {<br \/>\nfor (var j:Number=0; j&lt;=pic.height-1; j = j + sampling) {<br \/>\n\/\/read pixel (i,j)<br \/>\nx0 = i + sampleFuzzX*sampling*(2*Math.random()-1);<br \/>\ny0 = j + sampleFuzzY*sampling*(2*Math.random()-1);<br \/>\n\/\/create particle<br \/>\nc = pic.bitmapData.getPixel32(x0,y0);<br \/>\nvar p:Particle3D = new Particle3D(c);<br \/>\n\/\/set picture-based coordinates<br \/>\np.picX =  spread*(x0 &#8211; originX);<br \/>\np.picY =  spread*(y0 &#8211; originY);<br \/>\n\/\/add to array<br \/>\nthis.particleArray.push(p);<br \/>\n}<br \/>\n}<br \/>\ndispatchEvent(new Event(PictureAtomizer.PARTICLES_CREATED));<br \/>\n}<br \/>\npublic function setProjectionCoords(fLen:Number):void {<br \/>\nvar m:Number;<br \/>\nvar p:Particle3D;<br \/>\nfor (var t=0; t&lt;= _particleArray.length &#8211; 1; t++) {<br \/>\np = _particleArray[t];<br \/>\nm = fLen\/(fLen &#8211; p.w);<br \/>\np.projX = p.u*m + originX;<br \/>\np.projY = p.v*m + originY;<br \/>\n}<br \/>\n}<br \/>\npublic function setPositionsByPic(offsetX:Number, offsetY:Number, z0:Number):void {<br \/>\nvar p:Particle3D;<br \/>\nfor (var t=0; t&lt;= _particleArray.length &#8211; 1; t++) {<br \/>\np = _particleArray[t];<br \/>\np.x = p.picX + offsetX;<br \/>\np.y = p.picY + offsetY;<br \/>\np.z = z0;<br \/>\n}<br \/>\n}<br \/>\npublic function setGlobalAlpha(globalAlpha:Number):void {<br \/>\nvar c:uint;<br \/>\nvar p:Particle3D;<br \/>\ntrace(_particleArray.length);<br \/>\nfor (var t=0; t&lt;= _particleArray.length &#8211; 1; t++) {<br \/>\np = _particleArray[t];<br \/>\np.setColor((uint(255*globalAlpha) &lt;&lt; 24) | (p.color &amp; 0x00FFFFFF));<br \/>\n}<br \/>\n}<\/p>\n<p>public function buildDestinationArrays(numDestinations:Number):void {<br \/>\nvar p:Particle3D;<br \/>\nfor (var t=0; t&lt;= _particleArray.length &#8211; 1; t++) {<br \/>\np = _particleArray[t];<br \/>\nfor (var n:Number = 0; n &lt;= numDestinations-1; n++) {<br \/>\nvar thisPoint3D:Point3D = new Point3D();<br \/>\np.dest.push(thisPoint3D);<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\npublic function get particleArray():Array {<br \/>\nreturn _particleArray;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>7. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cParticleBoard\u201d in \u201cdisplay\u201d:<br \/>\npackage main.submain.display {<br \/>\nimport flash.display.*;<br \/>\nimport main.submain.objects.Particle3D;<br \/>\nimport main.submain.geom3D.*;<br \/>\npublic class ParticleBoard extends Bitmap {<br \/>\npublic var zBuffer:Array;<br \/>\npublic var fLen:Number;<br \/>\npublic var projOriginX:Number;<br \/>\npublic var projOriginY:Number;<br \/>\n\/\/darkening related variables<br \/>\nprivate var useDepthDarken:Boolean;<br \/>\nprivate var A:Number;<br \/>\nprivate var expRate:Number;<br \/>\nprivate var maxBrighten:Number;<br \/>\nprivate var bgColor;<br \/>\n\/\/Vars used in functions<br \/>\nprivate var f:Number;<br \/>\nprivate var m:Number;<br \/>\nprivate var dColor:uint;<br \/>\nprivate var intX:int;<br \/>\nprivate var intY:int;<br \/>\nprivate var p:Particle3D;<br \/>\nprivate var X2:Number;<br \/>\nprivate var Y2:Number;<br \/>\nprivate var Z2:Number;<br \/>\nprivate var wX:Number;<br \/>\nprivate var wY:Number;<br \/>\nprivate var wZ:Number;<br \/>\nprivate var xX:Number;<br \/>\nprivate var xY:Number;<br \/>\nprivate var xZ:Number;<br \/>\nprivate var yY:Number;<br \/>\nprivate var yZ:Number;<br \/>\nprivate var zZ:Number;<br \/>\npublic var frame:Shape;<br \/>\npublic var holder:Sprite;<br \/>\n\/*<br \/>\nframe = new Shape();<br \/>\nframe.graphics.lineStyle(2,0&#215;444444);<br \/>\nframe.graphics.drawRect(0,0,board.width,board.height);<br \/>\nframe.x = 0;<br \/>\nframe.y = 0;<br \/>\nboardHolder = new Sprite();<br \/>\nboardHolder.x = stage.stageWidth\/2 &#8211; board.width\/2;<br \/>\nboardHolder.y = stage.stageHeight\/2 &#8211; board.height\/2;<br \/>\nstage.addChild(boardHolder);<br \/>\nboardHolder.addChild(board);<br \/>\nboardHolder.addChild(frame);<br \/>\n*\/<br \/>\npublic function ParticleBoard(w, h, transp=true, fillColor = 0x00000000, _fLen=200) {<br \/>\nvar thisData:BitmapData = new BitmapData(w, h, transp, fillColor)<br \/>\nthis.bitmapData = thisData;<br \/>\nthis.zBuffer = [];<br \/>\nthis.useDepthDarken = false; \/\/changed to true in setDepthDarken<br \/>\nthis.projOriginX = w\/2;<br \/>\nthis.projOriginY = h\/2;<br \/>\nthis.fLen = _fLen;<br \/>\nthis.bgColor = fillColor;<br \/>\nthis.holder = new Sprite();<br \/>\nthis.holder.addChild(this);<br \/>\nthis.x = 0;<br \/>\nthis.y = 0;<br \/>\n}<br \/>\npublic function makeFrame(thick:Number, c:uint, inputAlpha:Number):void {<br \/>\nthis.frame = new Shape();<br \/>\nthis.frame.graphics.lineStyle(thick, c, inputAlpha);<br \/>\nthis.frame.graphics.drawRect(0,0,this.width,this.height);<br \/>\nthis.frame.x = 0;<br \/>\nthis.frame.y = 0;<br \/>\nthis.holder.addChild(frame);<br \/>\n}<br \/>\npublic function setDepthDarken(unityDepth:Number, halfDepth:Number, _maxBrighten):void {<br \/>\nthis.useDepthDarken = true;<br \/>\nthis.A = Math.pow(2, unityDepth\/(halfDepth-unityDepth));<br \/>\nthis.expRate = Math.LN2\/(unityDepth-halfDepth);<br \/>\nthis.maxBrighten = _maxBrighten;<br \/>\n}<br \/>\npublic function clearBoard(particles:Array):void {<br \/>\nfor (var i:Number = 0; i&lt;=particles.length-1; i++) {<br \/>\np = particles[i];<br \/>\nif (p.onScreen) {<br \/>\nintX = int(p.projX);<br \/>\nintY = int(p.projY);<br \/>\nzBuffer[intX+this.height*intY] = Number.NEGATIVE_INFINITY;<br \/>\n\/\/could also insert the code below to erase pixels,  but my method has been to use a blur filter and a colorTransform applied to whole bitmap, which creates &#8220;ghost&#8221; which fades out after a few frames. this.bitmapData.setPixel32(intX, intY, bgColor);<br \/>\n}<br \/>\n}<br \/>\n}\/\/end of clearBoard<br \/>\npublic function drawParticles(particles:Array, q:Quaternion):void {<br \/>\n\/\/clear the zBuffer<br \/>\nclearBoard(particles);<br \/>\nfor (var i:Number = 0; i&lt;=particles.length-1; i++) {<br \/>\np = particles[i];<br \/>\n\/\/viewpoint-relative coordinates found by quaternion rotation. Quaternion has been converted to rotation matrix, using common subexpressions for efficiency.  \t\t\t\t\tX2 = 2*q.x;<br \/>\nY2 = 2*q.y;<br \/>\nZ2 = 2*q.z;<br \/>\nwX = q.w*X2;<br \/>\nwY = q.w*Y2;<br \/>\nwZ = q.w*Z2;<br \/>\nxX = q.x*X2;<br \/>\nxY = q.x*Y2;<br \/>\nxZ = q.x*Z2;<br \/>\nyY = q.y*Y2;<br \/>\nyZ = q.y*Z2;<br \/>\nzZ = q.z*Z2;<br \/>\np.u = (1-(yY+zZ))*p.x + (xY-wZ)*p.y + (xZ+wY)*p.z;<br \/>\np.v = (xY+wZ)*p.x + (1-(xX+zZ))*p.y + (yZ-wX)*p.z;<br \/>\np.w = (xZ-wY)*p.x + (yZ+wX)*p.y + (1-(xX+yY))*p.z;<br \/>\n\/\/Projection coordinates<br \/>\nm = fLen\/(fLen &#8211; p.w);<br \/>\np.projX = p.u*m + projOriginX;<br \/>\np.projY = p.v*m + projOriginY;<br \/>\n\/\/test if particle is in viewable region<br \/>\nif ((p.projX &gt; this.width)||(p.projX&lt;0)||(p.projY&lt;0)||(p.projY&gt;this.height)||(p.w&gt;fLen-1)) {<br \/>\np.onScreen = false;<br \/>\n}<br \/>\nelse {<br \/>\np.onScreen = true;<br \/>\n}<br \/>\n\/\/drawing<br \/>\nintX = int(p.projX);<br \/>\nintY = int(p.projY);<br \/>\nif (p.onScreen) {<br \/>\nif (!(p.w &lt; zBuffer[intX+this.height*intY])) {<br \/>\nif (this.useDepthDarken) {<br \/>\n\/\/position-based darkening &#8211; exponential<br \/>\nf = A*Math.exp(expRate*p.w);<br \/>\nif (f&gt;maxBrighten) {<br \/>\nf = maxBrighten;<br \/>\n}<br \/>\ndColor = (0xFF000000) |(Math.min(255,f*p.red) &lt;&lt; 16) | (Math.min(255,f*p.green) &lt;&lt; 8 ) | (Math.min(255,f*p.blue));<br \/>\nthis.bitmapData.setPixel32(intX, intY, dColor);<br \/>\n}<br \/>\nelse {<br \/>\nthis.bitmapData.setPixel32(intX, intY, p.color);<br \/>\n}<\/p>\n<p>this.zBuffer[intX+this.height*intY] = p.w;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n}\/\/end of drawParticles<br \/>\n}\/\/end of class definition<br \/>\n}<\/p>\n<p>8. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cRotatingParticleBoard\u201d in \u201cdisplay\u201d:<\/p>\n<p>package main.submain.display {<br \/>\nimport flash.display.*;<br \/>\nimport flash.events.*;<br \/>\nimport main.submain.objects.Particle3D;<br \/>\nimport main.submain.geom3D.*;<br \/>\nimport flash.events.MouseEvent;<br \/>\npublic class RotatingParticleBoard extends Bitmap {<br \/>\npublic var zBuffer:Array;<br \/>\npublic var fLen:Number;<br \/>\npublic var projOriginX:Number;<br \/>\npublic var projOriginY:Number;<br \/>\n\/\/darkening related variables<br \/>\nprivate var useDepthDarken:Boolean;<br \/>\nprivate var A:Number;<br \/>\nprivate var expRate:Number;<br \/>\nprivate var maxBrighten:Number;<br \/>\nprivate var bgColor;<br \/>\n\/\/Vars used in functions<br \/>\nprivate var f:Number;<br \/>\nprivate var m:Number;<br \/>\nprivate var dColor:uint;<br \/>\nprivate var intX:int;<br \/>\nprivate var intY:int;<br \/>\nprivate var p:Particle3D;<br \/>\nprivate var X2:Number;<br \/>\nprivate var Y2:Number;<br \/>\nprivate var Z2:Number;<br \/>\nprivate var wX:Number;<br \/>\nprivate var wY:Number;<br \/>\nprivate var wZ:Number;<br \/>\nprivate var xX:Number;<br \/>\nprivate var xY:Number;<br \/>\nprivate var xZ:Number;<br \/>\nprivate var yY:Number;<br \/>\nprivate var yZ:Number;<br \/>\nprivate var zZ:Number;<br \/>\npublic var frame:Shape;<br \/>\npublic var holder:Sprite;<br \/>\nprivate var v1:Point3D;<br \/>\nprivate var v2:Point3D;<br \/>\nprivate var rSquare:Number;<br \/>\nprivate var invR:Number;<br \/>\nprivate var mouseDragging:Boolean;<br \/>\nprivate var lastQ:Quaternion;<br \/>\nprivate var changeQ:Quaternion;<br \/>\nprivate var requestQ:Quaternion;<br \/>\nprivate var inside:Boolean;<br \/>\nprivate var numRadii:Number;<br \/>\npublic var arcballRad:Number;<br \/>\npublic var currentQ:Quaternion;<br \/>\npublic var autoQuaternion:Quaternion;<br \/>\npublic var easingRatio:Number;<br \/>\nprivate var s:Number;<br \/>\npublic function RotatingParticleBoard(w, h, transp=true, fillColor = 0x00000000, _fLen=200) {<br \/>\nvar thisData:BitmapData = new BitmapData(w, h, transp, fillColor)<br \/>\nthis.bitmapData = thisData;<br \/>\nthis.zBuffer = [];<br \/>\nthis.useDepthDarken = false; \/\/changed to true in setDepthDarken<br \/>\nthis.projOriginX = w\/2;<br \/>\nthis.projOriginY = h\/2;<br \/>\nthis.fLen = _fLen;<br \/>\nthis.bgColor = fillColor;<br \/>\nthis.holder = new Sprite();<br \/>\nthis.holder.addChild(this);<br \/>\nthis.x = 0;<br \/>\nthis.y = 0;<br \/>\nthis.arcballRad = 0.5*Math.sqrt(Math.pow(w,2)+Math.pow(h,2));<br \/>\nthis.lastQ = new Quaternion();<br \/>\nthis.currentQ = new Quaternion(1,0,0,0);<br \/>\nthis.autoQuaternion = new Quaternion(1,0,0,0);<br \/>\nthis.lastQ = this.currentQ.clone();<br \/>\nthis.requestQ = new Quaternion();<br \/>\nthis.changeQ = new Quaternion(1,0,0,0);<br \/>\nthis.v1 = new Point3D;<br \/>\nthis.v2 = new Point3D;<br \/>\nthis.mouseDragging = false;<br \/>\nthis.easingRatio = 0.4;<br \/>\nthis.holder.addEventListener(Event.ADDED_TO_STAGE, addListeners);<br \/>\n}<br \/>\nprivate function addListeners(evt:Event):void {<br \/>\nthis.holder.removeEventListener(Event.ADDED_TO_STAGE, addListeners);<br \/>\nthis.holder.addEventListener(MouseEvent.MOUSE_DOWN, onDown);<br \/>\nthis.holder.root.addEventListener(MouseEvent.MOUSE_UP, onUp);<br \/>\n}<br \/>\npublic function makeFrame(thick:Number, c:uint, inputAlpha:Number):void {<br \/>\nthis.frame = new Shape();<br \/>\nthis.frame.graphics.lineStyle(thick, c, inputAlpha);<br \/>\nthis.frame.graphics.drawRect(0,0,this.width,this.height);<br \/>\nthis.frame.x = 0;<br \/>\nthis.frame.y = 0;<br \/>\nthis.holder.addChild(frame);<br \/>\n}<br \/>\npublic function setDepthDarken(unityDepth:Number, halfDepth:Number, _maxBrighten):void {<br \/>\nthis.useDepthDarken = true;<br \/>\nthis.A = Math.pow(2, unityDepth\/(halfDepth-unityDepth));<br \/>\nthis.expRate = Math.LN2\/(unityDepth-halfDepth);<br \/>\nthis.maxBrighten = _maxBrighten;<br \/>\n}<br \/>\npublic function clearBoard(particles:Array):void {<br \/>\nfor (var i:Number = 0; i&lt;=particles.length-1; i++) {<br \/>\np = particles[i];<br \/>\nif (p.onScreen) {<br \/>\nintX = int(p.projX);<br \/>\nintY = int(p.projY);<br \/>\nzBuffer[intX+this.height*intY] = Number.NEGATIVE_INFINITY;<br \/>\n\/\/could also insert the code below to erase pixels,  but my method has been to use a blur filter and a colorTransform applied to whole bitmap, which creates &#8220;ghost&#8221; which fades out after a few frames. this.bitmapData.setPixel32(intX, intY, bgColor);<br \/>\n}<br \/>\n}<br \/>\n}\/\/end of clearBoard<br \/>\npublic function drawParticles(particles:Array):void {<br \/>\nclearBoard(particles);<br \/>\n\/\/\/\/\/\/\/\/\/\/\/<br \/>\n\/\/viewpoint change by mouse<br \/>\nif (mouseDragging) {<br \/>\nv2.x = (holder.mouseX-projOriginX)\/arcballRad;<br \/>\nv2.y = (holder.mouseY-projOriginY)\/arcballRad;<br \/>\nrSquare = v2.x*v2.x + v2.y*v2.y;<br \/>\n\/\/for mouse position outside Arcball perimeter:<br \/>\nif (rSquare &gt; 1) {<br \/>\ninvR = 1\/Math.sqrt(rSquare);<br \/>\nv2.x = v2.x*invR;<br \/>\nv2.y = v2.y*invR;<br \/>\nv2.z = 0;<br \/>\n}<br \/>\n\/\/for mouse position inside Arcball perimeter:<br \/>\nelse {<br \/>\nv2.z = Math.sqrt(1 &#8211; rSquare);<br \/>\ninside = true;<br \/>\n}<br \/>\n\/\/interpret mouse movement as request for rotation change<br \/>\nrequestQ.w = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;<br \/>\nrequestQ.x = v1.y*v2.z &#8211; v2.y*v1.z;<br \/>\nrequestQ.y = -v1.x*v2.z + v2.x*v1.z;<br \/>\nrequestQ.z = v1.x*v2.y &#8211; v2.x*v1.y;<br \/>\n\/\/smooth movement is accomplished by rotating only 40% towards the requested rotation in each frame.  After about ten frames,  the rotation will be within 1% of the requested rotation.<br \/>\nchangeQ.w += easingRatio*(requestQ.w &#8211; changeQ.w);<br \/>\nchangeQ.x += easingRatio*(requestQ.x &#8211; changeQ.x);<br \/>\nchangeQ.y += easingRatio*(requestQ.y &#8211; changeQ.y);<br \/>\nchangeQ.z += easingRatio*(requestQ.z &#8211; changeQ.z);<br \/>\n\/\/ensure that the change quaternion is a unit quaternion:<br \/>\ns = 1\/Math.sqrt(changeQ.w*changeQ.w +changeQ.x*changeQ.x+changeQ.y*changeQ.y+changeQ.z*changeQ.z);<br \/>\nchangeQ.w *= s;<br \/>\nchangeQ.x *= s;<br \/>\nchangeQ.y *= s;<br \/>\nchangeQ.z *= s;<br \/>\n}<br \/>\nelse {<br \/>\nlastQ = currentQ.clone();<br \/>\nchangeQ.w = autoQuaternion.w;<br \/>\nchangeQ.x = autoQuaternion.x;<br \/>\nchangeQ.y = autoQuaternion.y;<br \/>\nchangeQ.z = autoQuaternion.z;<br \/>\n}<br \/>\n\/\/find current resultant rotation by quaternion multiplication of<br \/>\nlastQ and changeQ<br \/>\ncurrentQ.w = changeQ.w*lastQ.w &#8211; changeQ.x*lastQ.x &#8211; changeQ.y*lastQ.y &#8211; changeQ.z*lastQ.z;<br \/>\ncurrentQ.x = changeQ.w*lastQ.x + lastQ.w*changeQ.x + changeQ.y*lastQ.z &#8211; lastQ.y*changeQ.z;<br \/>\ncurrentQ.y = changeQ.w*lastQ.y + lastQ.w*changeQ.y &#8211; changeQ.x*lastQ.z + lastQ.x*changeQ.z;<br \/>\ncurrentQ.z = changeQ.w*lastQ.z + lastQ.w*changeQ.z + changeQ.x*lastQ.y &#8211; lastQ.x*changeQ.y;<br \/>\n\/\/\/\/\/\/\/\/\/\/\/<br \/>\nfor (var i:Number = 0; i&lt;=particles.length-1; i++) {<br \/>\np = particles[i];<br \/>\n\/\/viewpoint-relative coordinates found by quaternion rotation. Quaternion has been converted to rotation matrix, usingcommon subexpressions for efficiency.<br \/>\nX2 = 2*currentQ.x;<br \/>\nY2 = 2*currentQ.y;<br \/>\nZ2 = 2*currentQ.z;<br \/>\nwX = currentQ.w*X2;<br \/>\nwY = currentQ.w*Y2;<br \/>\nwZ = currentQ.w*Z2;<br \/>\nxX = currentQ.x*X2;<br \/>\nxY = currentQ.x*Y2;<br \/>\nxZ = currentQ.x*Z2;<br \/>\nyY = currentQ.y*Y2;<br \/>\nyZ = currentQ.y*Z2;<br \/>\nzZ = currentQ.z*Z2;<br \/>\np.u = (1-(yY+zZ))*p.x + (xY-wZ)*p.y + (xZ+wY)*p.z;<br \/>\np.v = (xY+wZ)*p.x + (1-(xX+zZ))*p.y + (yZ-wX)*p.z;<br \/>\np.w = (xZ-wY)*p.x + (yZ+wX)*p.y + (1-(xX+yY))*p.z;<br \/>\n\/\/Projection coordinates<br \/>\nm = fLen\/(fLen &#8211; p.w);<br \/>\np.projX = p.u*m + projOriginX;<br \/>\np.projY = p.v*m + projOriginY;<br \/>\n\/\/test if particle is in viewable region<br \/>\nif ((p.projX &gt; this.width)||(p.projX&lt;0)||(p.projY&lt;0)||(p.projY&gt;this.height)||(p.w&gt;fLen-1)) {<br \/>\np.onScreen = false;<br \/>\n}<br \/>\nelse {<br \/>\np.onScreen = true;<br \/>\n}<br \/>\n\/\/drawing<br \/>\nintX = int(p.projX);<br \/>\nintY = int(p.projY);<br \/>\nif (p.onScreen) {<br \/>\nif (!(p.w &lt; zBuffer[intX+this.height*intY])) {<br \/>\nif (this.useDepthDarken) {<br \/>\n\/\/position-based darkening &#8211; exponential<br \/>\nf = A*Math.exp(expRate*p.w);<br \/>\nif (f&gt;maxBrighten) {<br \/>\nf = maxBrighten;<br \/>\n}<br \/>\ndColor = (0xFF000000) |(Math.min(255,f*p.red) &lt;&lt; 16) | (Math.min(255,f*p.green) &lt;&lt; 8) | (Math.min(255,f*p.blue));<br \/>\nthis.bitmapData.setPixel32(intX, intY, dColor);<br \/>\n}<br \/>\nelse {<br \/>\nthis.bitmapData.setPixel32(intX, intY, p.color);<br \/>\n}<br \/>\nthis.zBuffer[intX+this.height*intY] = p.w;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n}\/\/end of drawParticles<br \/>\nprivate function onDown(evt:MouseEvent):void {<br \/>\nmouseDragging = true;<br \/>\nchangeQ = new Quaternion(1,0,0,0);<br \/>\nlastQ = currentQ.clone();<br \/>\nv1.x = (holder.mouseX-projOriginX)\/arcballRad;<br \/>\nv1.y = (holder.mouseY-projOriginY)\/arcballRad;<br \/>\nrSquare = v1.x*v1.x + v1.y*v1.y;<br \/>\nif (rSquare &gt; 1) {<br \/>\ninvR = 1\/Math.sqrt(rSquare);<br \/>\nv1.x = v1.x*invR;<br \/>\nv1.y = v1.y*invR;<br \/>\nv1.z = 0;<br \/>\ninside = false;<br \/>\n}<br \/>\nelse {<br \/>\nv1.z = Math.sqrt(1 &#8211; rSquare);<br \/>\ninside = true;<br \/>\n}<br \/>\n}<br \/>\nprivate function onUp(evt:MouseEvent):void {<br \/>\nmouseDragging = false;<br \/>\n}<br \/>\n}\/\/end of class definition<br \/>\n}<\/p>\n<p>9. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cPoint3D\u201d in \u201cgeom3D\u201d:<\/p>\n<p>package main.submain.geom3D {<br \/>\npublic class Point3D {<br \/>\npublic var x:Number;<br \/>\npublic var y:Number;<br \/>\npublic var z:Number;<br \/>\npublic function Point3D(x1=0,y1=0,z1=0):void {<br \/>\nthis.x = x1;<br \/>\nthis.y = y1;<br \/>\nthis.z = z1;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>10. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cQuaternion\u201d in \u201cgeom3D\u201d:<\/p>\n<p>package main.submain.geom3D {<br \/>\npublic class Quaternion {<br \/>\npublic var w;<br \/>\npublic var x;<br \/>\npublic var y;<br \/>\npublic var z;<br \/>\npublic function Quaternion(_w=0,_x=0, _y=0, _z=0) {<br \/>\nthis.w = _w;<br \/>\nthis.x = _x;<br \/>\nthis.y = _y;<br \/>\nthis.z = _z;<br \/>\n}<br \/>\npublic function clone():Quaternion {<br \/>\nreturn new Quaternion(this.w, this.x, this.y, this.z);<br \/>\n}}}<\/p>\n<p>11. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cIndexedLoader\u201d in \u201cloaders\u201d:<\/p>\n<p>package main.submain.loaders {<br \/>\nimport flash.display.Loader;<br \/>\npublic class IndexedLoader extends Loader {<br \/>\npublic var which:Number;<br \/>\npublic var done:Boolean;<br \/>\nfunction IndexedLoader(inputIndex):void {<br \/>\nthis.which = inputIndex;<br \/>\nthis.done = false;<br \/>\n}}}<\/p>\n<p>12. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cPictureLoader\u201d in \u201cloaders\u201d:<\/p>\n<p>package main.submain.loaders {<br \/>\nimport flash.display.*;<br \/>\nimport flash.events.*;<br \/>\nimport flash.net.URLRequest;<br \/>\nimport main.submain.loaders.IndexedLoader;<br \/>\npublic class PictureLoader extends EventDispatcher {<br \/>\npublic static const ALL_PICS_LOADED:String=&#8221;allPicsLoaded&#8221;;<br \/>\nprivate function dispatch():void {<br \/>\ndispatchEvent(new Event(PictureLoader.ALL_PICS_LOADED));<br \/>\n}<br \/>\npublic var picURLArray:Array = [];<br \/>\nprivate var picLoader:Array = [];<br \/>\nprivate var pic:Array=[];<br \/>\nprivate var loadCount:Number;<br \/>\npublic var failPicSize:Number;<br \/>\npublic var useFailPic:Boolean;<br \/>\npublic function PictureLoader(_useFailPic = true, _failPicSize = 16) {<br \/>\nthis.useFailPic = _useFailPic;<br \/>\nthis.failPicSize = _failPicSize;<br \/>\n}<br \/>\npublic function loadPics(inputURLArray:Array):void {<br \/>\npicURLArray = inputURLArray;<br \/>\npic = [];<br \/>\nloadCount = 0;<br \/>\nsetUpLoaders();<br \/>\n}<br \/>\nprivate function failPic():Sprite {<br \/>\nvar thisPic:Sprite = new Sprite();<br \/>\nthisPic.graphics.lineStyle(2,0xdddddd);<br \/>\nthisPic.graphics.beginFill(0x000000);<br \/>\nthisPic.graphics.drawRect(0,0,failPicSize,failPicSize);<br \/>\nthisPic.graphics.endFill();<br \/>\nthisPic.graphics.lineStyle(2,0xdd0000);<br \/>\nthisPic.graphics.moveTo(2,2);<br \/>\nthisPic.graphics.lineTo(failPicSize-2,failPicSize-2);<br \/>\nthisPic.graphics.moveTo(failPicSize-2,2);<br \/>\nthisPic.graphics.lineTo(2,failPicSize-2);<br \/>\nreturn thisPic;<br \/>\n}<br \/>\nprivate function cleanUp():void {<br \/>\nvar errorPic:Array = [];<br \/>\nfor (var n:Number=0; n&lt;= picURLArray.length-1; n++) {<br \/>\nif (pic[n]==null) {<br \/>\n\/\/trace(&#8220;Picture &#8220;+String(n)+&#8221; not loaded.&#8221;);<br \/>\npicLoader[n].contentLoaderInfo.removeEventListener(Event.INIT, initListener);<br \/>\npicLoader[n].contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);<br \/>\nerrorPic.push(n);<br \/>\n}<br \/>\n}<br \/>\nif (useFailPic) {<br \/>\n\/\/place fail pic in bad spots<br \/>\nif (errorPic.length != 0) {<br \/>\nfor (n = 0; n&lt;= errorPic.length &#8211; 1; n++) {<br \/>\nvar thisBitmapData:BitmapData = new BitmapData(failPicSize, failPicSize);<br \/>\nvar thisBitmap:Bitmap = new Bitmap(thisBitmapData);<br \/>\nthisBitmapData.draw(failPic());<br \/>\npic[errorPic[n]] = thisBitmap;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nelse {<br \/>\n\/\/remove error pics from pic array<br \/>\nif (errorPic.length != 0) {<br \/>\nfor (n = 0; n&lt;= errorPic.length &#8211; 1; n++) {<br \/>\npic.splice(errorPic[n],1);<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nprivate function setUpLoaders():void {<br \/>\nvar thisURL:URLRequest; \/\/create a loader for each picture, to load simultaneously.<br \/>\nfor (var n:Number=0; n&lt;= picURLArray.length-1; n++) {<br \/>\nvar thisLoader:IndexedLoader = new IndexedLoader(n);<br \/>\npicLoader.push(thisLoader);<br \/>\npicLoader[n].load(new URLRequest(picURLArray[n]));<br \/>\npicLoader[n].contentLoaderInfo.addEventListener(Event.INIT, initListener);<br \/>\npicLoader[n].contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);<br \/>\n}<br \/>\n}<br \/>\nprivate function errorHandler(evt:ErrorEvent):void {<br \/>\nloadCount++;<br \/>\nif (loadCount == picURLArray.length) {<br \/>\ncleanUp();<br \/>\ndispatch();<br \/>\n}<br \/>\n}<br \/>\nprivate function initListener(evt:Event):void {<br \/>\n\/\/copy loaded picture to pic array<br \/>\ntry {<br \/>\nvar n:Number = evt.currentTarget.loader.which;<br \/>\n\/\/trace(&#8220;picture &#8220;+String(n)+&#8221; loaded.&#8221;);<br \/>\npic[n] = Bitmap(picLoader[n].content);<br \/>\n}<br \/>\ncatch (err:Error) {<br \/>\n\/\/trace(&#8220;picture &#8220;+String(n)+&#8221; unsuccessful.&#8221;);<br \/>\n}<br \/>\n\/\/remove event listener<br \/>\npicLoader[n].contentLoaderInfo.removeEventListener(Event.INIT, initListener);<br \/>\nloadCount++;<br \/>\nif (loadCount == picURLArray.length) {<br \/>\ncleanUp();<br \/>\ndispatch();<br \/>\n}<br \/>\n}<br \/>\npublic function get picArray():Array {<br \/>\nreturn pic;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>12. Again open actionscript file by press ctrl+n. Copy and paste the following code and save it as \u201cParticle3D\u201d in \u201cobjects\u201d:<\/p>\n<p>package main.submain.objects {<br \/>\nimport flash.display.*;<br \/>\nimport main.submain.geom3D.*;<br \/>\npublic class Particle3D extends Point3D {<br \/>\n\/\/links, for creating linked lists<br \/>\npublic var next:Particle3D;<br \/>\npublic var prev:Particle3D;<br \/>\npublic var onScreen:Boolean;<br \/>\n\/\/velocity and acceleration vectors<br \/>\npublic var vel:Point3D = new Point3D();<br \/>\npublic var accel:Point3D = new Point3D();<br \/>\npublic var lastX:Number;<br \/>\npublic var lastY:Number;<br \/>\npublic var lastZ:Number;<br \/>\n\/\/projected coordinates<br \/>\npublic var projX:Number;<br \/>\npublic var projY:Number;<br \/>\n\/\/coords WRT viewpoint axes<br \/>\npublic var u:Number;<br \/>\npublic var v:Number;<br \/>\npublic var w:Number;<br \/>\n\/\/location in source picture<br \/>\npublic var picX:Number;<br \/>\npublic var picY:Number;<br \/>\n\/\/destination array<br \/>\npublic var dest:Array;<br \/>\n\/\/attributes<br \/>\npublic var color:uint;<br \/>\npublic var red:Number;<br \/>\npublic var green:Number;<br \/>\npublic var blue:Number;<br \/>\npublic var lum:Number;<br \/>\npublic var alpha:Number;<br \/>\npublic var initColor:uint;<br \/>\npublic var initRed:Number;<br \/>\npublic var initGreen:Number;<br \/>\npublic var initBlue:Number;<br \/>\npublic var initLum:Number;<br \/>\npublic var destColor:uint;<br \/>\npublic var destRed:Number;<br \/>\npublic var destGreen:Number;<br \/>\npublic var destBlue:Number;<br \/>\npublic var destLum:Number;<br \/>\npublic var colorChanging:Boolean;<br \/>\nfunction Particle3D(thisColor=0xFFFFFFFF):void {<br \/>\nthis.dest = [];<br \/>\nthis.color = thisColor;<br \/>\nthis.red = getRed(thisColor);<br \/>\nthis.green = getGreen(thisColor);<br \/>\nthis.blue = getBlue(thisColor);<br \/>\nthis.alpha = getAlpha(thisColor);<br \/>\nthis.lum = 0.2126*this.red + 0.7152*this.green + 0.0722*this.blue;<br \/>\nthis.colorChanging = false;<br \/>\nthis.onScreen = true;<br \/>\n}<br \/>\npublic function setColor(thisColor):void {<br \/>\nthis.color = thisColor;<br \/>\nthis.red = getRed(thisColor);<br \/>\nthis.green = getGreen(thisColor);<br \/>\nthis.blue = getBlue(thisColor);<br \/>\nthis.alpha = getAlpha(thisColor);<br \/>\nthis.lum = 0.2126*this.red + 0.7152*this.green + 0.0722*this.blue;<br \/>\n}<br \/>\npublic function getAlpha(c):Number {<br \/>\nreturn Number((c &gt;&gt; 24) &amp; 0xFF);<br \/>\n}<br \/>\npublic function getRed(c):Number {<br \/>\nreturn Number((c &gt;&gt; 16) &amp; 0xFF);<br \/>\n}<br \/>\npublic function getGreen(c):Number {<br \/>\nreturn Number((c &gt;&gt; 8) &amp; 0xFF);<br \/>\n}<br \/>\npublic function getBlue(c):Number {<br \/>\nreturn Number(c &amp; 0xFF);<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>Run the program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Open a new document and set background color as black. 2. Select Layer-1, Keyframe 1. Press F9 to write the following action script. I have explained the code in the comments. import fl.motion.easing.Quartic; import fl.motion.easing.Bounce; import fl.motion.Animator3D; import main.submain.loaders.*; import main.submain.bitmapUtilities.PictureAtomizer; import main.submain.objects.Particle3D; import main.submain.geom3D.*; import main.submain.display.*; var picURLString:Array; \/\/ var is a variables, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[31],"class_list":["post-536","post","type-post","status-publish","format-standard","hentry","category-flash","tag-3d-flower-twist-in-flash"],"_links":{"self":[{"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/posts\/536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/comments?post=536"}],"version-history":[{"count":20,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/posts\/536\/revisions"}],"predecessor-version":[{"id":538,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/posts\/536\/revisions\/538"}],"wp:attachment":[{"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/media?parent=536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/categories?post=536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.searchenginegenie.com\/web-design-blog\/wp-json\/wp\/v2\/tags?post=536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}