国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

Java 3D的動畫展示(Part1-使用JMF)

瀏覽:87日期:2024-06-12 13:15:54
內容: Java 3D的動畫展示(Part1-使用JMF)翻譯:Andrew Davison, Killer Game Programming in Java的作者06/01/2005 翻譯 Caesh版權聲明:可以任意轉載,轉載時請務必以超鏈接形式標明文章原始出處和作者信息及本聲明英文原文地址:http://www.onjava.com/pub/a/onjava/2005/06/01/kgpjava.html中文地址:http://www.matrix.org.cn/resource/article/43/43675_Java_3D.html關鍵詞: Java 3D JMF在Java 3D場景中插入動畫片段使3D內容更加有趣充實.一段動畫可以在更令人信服的背景下展示,例如飄動的云,繁忙的城市街道,或者是從窗向外看的效果.動畫可以在屏幕效果和游戲效果之間任意轉換.這篇文章被分為兩個部分,描寫我怎樣實現一個Java 3D動畫屏幕效果.在這個部分,我將說明我怎樣利用JMF(Java Media Framework),特別是在JMF Performance Pack for Windows v.2.1.1e情況下.我的另外兩個工具是J2SE 5.0和Java 3D 1.3.2.我將討論另外的使用Quicktime for Java的動畫屏幕版本.圖1是應用JMF Movie3D在不同時間截取的兩幅截屏,右邊截屏是從屏幕后看的效果. 圖1. Movie3D應用截屏此應用程序中重點:。JMF和Java 3D的集成.屏幕以任意尺寸成倍增加在一個應用程序.由于屏幕是Java3D的Shape3D類的一個子類,因此它可以很容易的統一到各種Java 3D場景中.。程序執行使用Model-View-Controller設計模式.屏幕是一個視頻元素,由JMFMovieScreen類描述.動畫是一個由JMFSnapper類控制的模型部分.一個Java 3D Behavior類,TimeBehavior,控制動畫定時定期更新.所有JMF編碼都存放在JMFSnapper類,可以很方便的測試各種變化.這篇文章的第二部分JMFSnapper由QuickTime for Java版本中的QTSnapper取代.。Java 3D 的使用將會使動畫的播放速度毫無困難的上升到25幀/秒.。使用JMF出現問題的討論.問題是我首選解決方案將不會工作-JMF有可能變為一個巨大的API,但在其內部仍有一些程序沒有及時運行.1. 我坐在山上事實上,我正坐在一個冰冷的辦公室.我真正的意思是說這篇文章建立在大量Java 3D和JMF背景知識之上.我將不會細致地解釋Java 3D的基礎知識,因為它們都可以在O'Reilly文章Killer Game Programming in Java(以下簡稱KGPJ)中找到.例如,圖1場景效果圖是其第15章中的輕微改良Checkers3D的版本實例.我再生了這些編碼以生成底版,藍天和燈光.假如你不想買這本書,沒關系,所有篇章的初稿和所有編碼都可以在此書的站點查閱.在此文章中,我將會解釋我用來從動畫中抽取幀的JMF技術.我將不會討論流媒體或者編碼轉換.2. 應用簡述動畫由JMFSnapper類加載播放,并且不斷的循環播放直到被停止.JMFMovieScreen生成動畫屏幕,并在底版上控制Java 3D四邊形.圖2顯示這些類的應用(該場景圖說明場景中Java 3D節點怎樣連接在一起) 圖2:Movie3D場景圖圖2種的很多細節可以被忽略,此圖KGPJ15章中的得Checkers3D實例有很多相似之處. 只有特殊動畫的節點是新的.由于節點關系,JMFMovieScreen和TimeBehavior對象以三角形表示.JMFSnapper對象不屬于這張圖,但由JMFMovieScreen調用.每40毫秒,TimeBehavior對象調用JMFMovieScreen類中的nextFrame()方法.接下來調用JMFSnapper中的getFrame()方法獲取動畫中當前播放的幀,由JMFMovieScreen控制成像.TimeBehavior是Java 3D的Behavior類的子類,它是Java 3D應用的計時器.它與KGPJ18章中的3D sprites實例中的TimeBehavior類十分相似.觀察應用過程的另一種方式就是察看它的UML類圖表,圖3給出。類中的公共方法被顯示.圖3:Movie3D類圖表Movie3D的子類JFrame,WrapMovie3D是JPanel的一個子類.圖2展示了WrapMovie3D如何構建場景圖,和將其譯成應用的JPanel.他使用CheckerFloor 和ColouredTiles類構建底版.JMFMovieScreen創建動畫屏幕,將其加入場景中,通過創建一個JMFSnapper對象開始動畫.TimeBehavior每40毫秒調用JMFMovieScreen中的nextFrame()方法. nextFrame()調用JMFSnapper中的getFrame()得到當前幀. 這個例子中的所有編碼,此文章的早期版本可以在KGPJ網點查詢.3. 準備動畫動畫,它的屏幕和更新屏幕的TimeBehavior對象,都是由WrapMovie3D中的addMovieScreen()方法創立.// globalsprivate BranchGroup sceneBG;private JMFMovieScreen ms; // the movie screenprivate TimeBehavior timer; // to update screenprivate void addMovieScreen(String fnm){ // put the movie in fnm onto a movie screen ms = new JMFMovieScreen( new Point3f(1.5f, 0, -1), 2.0f, fnm); sceneBG.addChild(ms); // set up the timer for animating the movie timer = new TimeBehavior(40, ms); // update movie every 40ms (== 25 frames/sec) timer.setSchedulingBounds(bounds); sceneBG.addChild(timer);} 兩個Java 3D addChild()方法調用JMFMovieScreen和TimeBehavior節點間的連接.setSchedulingBounds()激活TimeBehavior節點.4. 創建動畫屏幕JMFMovieScreen是Java 3D的Shape3D類的一個子類.所以必須仔細說明它的外形的幾何形狀和外觀.幾何形狀是指動畫圖像的四個邊尺寸上成比例,它的最大尺寸(高 寬)必須向構造器仔細說明.這個四方形是垂直的,朝向Z軸正方向,可以在底版的任何位置被定位.四方形外觀是雙面,允許從前或后觀看動畫.結構是用雙線性插值,可以降低動畫圖像的像素化.大多數的功能是從KGPJ24章中的FPS(first-person shooter)實例中的ImageCsSeries類拷貝而來. ImageCsSeries在一個區域中顯示一系列的GIF圖片. 為了簡短起見,我僅描述了JMFMovieScreen與ImageCsSeries的不同特征.高效顯示圖像動畫中的一個幀被轉換結構擴大四倍;分為兩個步驟:第一步 提供的BufferedImage傳給Java 3D的ImageComponent2D對象,然后傳給Java 3D Texture2D.區域的圖像更新非常快:每秒更新25幀,要求結構更新25次.因此結構有效率的更新非常的重要.這種高效率在利用BufferedImage和ImageComponent2D對象進行格式化的情況下是可能的.JMFMovieScreen使用的ImageComponent2D對象以以下方式聲明:ImageComponent2D ic = new ImageComponent2D( ImageComponent2D.FORMAT_RGB, FORMAT_SIZE, FORMAT_SIZE, true, true);構造器剩余兩個需要說明的討論點是它使用'by reference'和'Y-up'模式.這些模式降低了存儲結構圖像的內存大小,因為Java 3D避免將圖像從應用空間拷貝到圖形內存. 在Windows OS環境下,使用OpenGL作為Java 3D優先圖像引擎,ImageComponent2D格式應是ImageComponent2D.FORMAT_RGB,BufferedImage格式應是BufferedImage.TYPE_3BYTE_BGR.BufferedImage格式在JMFSnapper中確定.此項技術的更多細節可以在j3d.org中查詢.將紋理加進區域通常在一個區域中確定一幅圖像的方法是將圖像的坐下角連接到區域的左下角,然后逆時針連接剩余的幾個角.圖4說明這種方法. 圖4.圖像與區域之間的標準連接圖像坐標區間在X Y軸的0 1之間,Y軸正方向.例如,圖像左下點坐標為(0,0),右上點為(1,1).當'Y-up'模式使用,圖像坐標Y軸翻轉,負方向.意味著(0,0)代表圖像左上點,(1,1)指向右下.當'Y-up'模式建立,圖像坐標必須分配給區域中不同點以便獲得圖像的相同定位.圖5顯示了最新配置. 圖5.'Y-up'模式使用時,圖像與區域之間的連接連接區域點與圖像定位的JMFMovieScreen編碼是TexCoord2f q = new TexCoord2f();q.set(0.0f, 0.0f); plane.setTextureCoordinate(0, 3, q); // (0,0) tex coord top left quad point (p3)q.set(1.0f, 0.0f); plane.setTextureCoordinate(0, 2, q); // (1,0) top right (p2)q.set(1.0f, 1.0f); plane.setTextureCoordinate(0, 1, q); // (1,1) bottom right (p1)q.set(0.0f, 1.0f); plane.setTextureCoordinate(0, 0, q); // (0,1) bottom left (p0)PLANE對象指代區域.更新圖像以上所講,TimeBehavior是被設置用來被40毫秒調用JMFMovieScreen的nextFrame()方法.nextFrame()調用JMFSnapper對象中的getFrame()方法獲得被看作BufferedImage對象的當前動畫幀.指派給一個mageComponent2D對象,然后傳給區域圖像.nextFrame()是:// globalsprivate Texture2D texture; // used by the quadprivate ImageComponent2D ic;private JMFSnapper snapper; // to take snaps of the movieprivate boolean isStopped = false; // is the movie stopped?public void nextFrame(){ if (isStopped) // movie has been stopped return; BufferedImage im = snapper.getFrame();// get current frame if (im != null) { ic.set(im); //assign frame to ImageComponent2D texture.setImage(0,ic); // make it the shape's texture } else System.out.println('Null BufferedImage');}snapper,JMFSnapper對象,由JMFMovieScreen的構造器創建:// load and play the moviesnapper = new JMFSnapper(movieFnm);JMFSnapper的簡單接口掩蓋了播放動畫和從動畫中抽取幀的JMF編碼的復雜.著這個系列的第二部分,JMFSnapper由使用QuickTime for Java的版本取代,對JMFMovieScreen只需要作出微小改動.5. 管理動畫JMF提供了一種訪問動畫幀的高水平方法.以下的編碼片斷闡明了主要元素.我將省去錯誤檢驗和異常處理.// create a movie player, in a 'realized' stateURL url = new URL('file:' + movieFnm);Player p = Manager.createRealizedPlayer(url);// create a frame positionerFramePositioningControl fpc = (FramePositioningControl) p.getControl('javax.media.control. FramePositioningControl');// create a frame grabberFrameGrabbingControl fg = (FrameGrabbingControl) p.getControl('javax.media.control. FrameGrabbingControl');// request that the player changes to a 'prefetched' statep.prefetch();// wait until the player is in that state...// move to a particular frame, e.g. frame 100fpc.seek(100); // take a snap of the current frameBuffer buf = fg.grabFrame(); // get its video format detailsVideoFormat vf = (VideoFormat) buf.getFormat();// initialize BufferToImage with video formatBufferToImage bufferToImage = new BufferToImage(vf);// convert the buffer to an imageImage im = bufferToImage.createImage(buf);// specify the format of desired BufferedImageBufferedImage formatImg = new BufferedImage( FORMAT_SIZE, FORMAT_SIZE, BufferedImage.TYPE_3BYTE_BGR);// convert the image to a BufferedImageGraphics g = formatImg.getGraphics();g.drawImage(im, 0, 0, FORMAT_SIZE, FORMAT_SIZE, null);g.dispose();一個媒體播放器從制作到完成需要六個步驟.播放器在構思過程中要清楚怎樣運行數據,可以在要求時提供視覺上的組成和控制器.我要求兩個控制器:FramePositioningControl和FrameGrabbingControl. FramePositioningControl提供了seek()和skip()方法,可以在動畫中查檢特殊幀.FrameGrabbingControl提供grabFrame()方法,可以在動畫的視頻軌跡中抽取當前幀.為了使這些控制器工作,播放器必須由構思過程進入構建過程.播放器開始準備播放媒體,媒體數據被加載.prefetch()的調用是異步的,意味著編碼必須等待直到轉換過程結束.標準JMF譯碼解決方案使用waitForState()方法,此方法將使執行過程暫停直到一個狀態轉換事件將其喚醒.如果想尋找一個幀,可以使用seek()方法在軌跡中將這個幀定位,然后利用grabFrame()方法提取.提取的Buffer對象轉變為JMFMovieScreen要求的 BufferedImage對象必須經過幾個轉變過程.注意:BufferedImage對象是TYPE_3BYTE_BGR格式.Sun公司的JMF website有很多很有用的小例子,其中之一,Seek.java展示了如何使用FramePositioningControl方法做成動畫.三步審查不幸的是,編碼大體上是錯誤的,至少在JMF Performance Pack for Windows v.2.1.1e.我審查了幾個編碼重寫以獲得可工作的JMFSnapper版本.1. 兩個控制器,FramePositioningControl和FrameGrabbingControl,在JMF下的缺省播放器模塊中是很難獲得的.'本地模塊'播放器被要求:Manager.setHint(Manager.PLUGIN_PLAYER, new Boolean(true));這個播放器組成龐大,對Swing GUIs例如JFrame和JPanel會產生弱化的影響.然而,我不需要展示這個播放器.使用本地模塊播放器會產生一系列嚴重的后果,媒體加載時間過長,無序播放.2.在一番沉思后,我確定了加速播放器的最佳方法是減少其工作量.我將音頻從MPEG文件剝離,確保文件以簡單的MPEG-1格式儲存.一些視頻編輯工具可以完成這些工作.我使用的是兩個免費的工具:MPEG Properties和FlasKMPEG.被剝離的動畫播放很順暢,幀率是一個常數,沒有幀遺漏.不過,FramePositioningControl類是不可靠的.在我的WinXP機器,seek()方法幾乎總是失敗,skip()方法五次也只能成功一次.3.我下定決心舍棄FramePositioningControl.我的幀抓取運算法則依賴每隔一段時間調用FrameGrabbingControl的grabFrame()方法當播放器播放動畫.我已有可以很可靠的從只有視頻的MPEG-1文件中抓取幀的編碼.它也可以從視頻音頻齊全的文件中還算不錯的抓取幀,但是播放器啟動會很慢.而且,無序播放會引起幀的不規律抓取.我在JMFSnapper前段加寫了“等待編碼以處理視頻-音頻文件.JMFSnapper對象等待播放器啟動和第一個動畫幀變的可用.等待第一幀JMFSnapper構造器調用waitForBufferToImage()方法以便重復的調用hasBufferToImage()直到它檢測到第一個視頻幀.hasBufferToImage()調用FrameGrabbingControl的grabFrame(),檢測返回的Buffer對象是否含有視頻信息數據.它使用這些數據初始化一個BufferToImage對象,此對象被用來將每一個抓取幀轉化為圖像.// globalsprivate FrameGrabbingControl fg; // frame grabberprivate BufferToImage bufferToImage = null;private int width, height; // frame dimensionsprivate boolean hasBufferToImage(){ Buffer buf = fg.grabFrame(); // take a snap if (buf == null) { System.out.println('No grabbed frame'); return false; } // there is a buffer, but check if it's empty VideoFormat vf = (VideoFormat) buf.getFormat(); if (vf == null) { System.out.println('No video format'); return false; } System.out.println('Video format: ' + vf); // extract the image's dimensions width = vf.getSize().width; height = vf.getSize().height; // initialize bufferToImage with video format bufferToImage = new BufferToImage(vf); return true;}這個編碼方法的一個微小缺點是第一個視頻幀(引起hasBufferToImage()返回true)在BufferToImage對象初始化后被丟棄.作為BufferedImage to JMFMovieScreen這個幀不能被使用.抓圖JMFSnapper中的最重要的公共方法是getFrame(),此方法被周期性的調用以獲得播放動畫中的當前幀.// globalprivate BufferedImage formatImg; // frame imagesynchronized public BufferedImage getFrame(){ // grab the current frame as a buffer object Buffer buf = fg.grabFrame(); if (buf == null) { System.out.println('No grabbed buffer'); return null; } // convert buffer to image Image im = bufferToImage.createImage(buf); if (im == null) { System.out.println('No grabbed image'); return null; } // convert the image to a BufferedImage Graphics g = formatImg.getGraphics(); g.drawImage(im, 0, 0, FORMAT_SIZE, FORMAT_SIZE, null); // Overlay current time on top of the image g.setColor(Color.RED); g.setFont(new Font('Helvetica',Font.BOLD,12)); g.drawString(timeNow(), 5, 14); g.dispose(); return formatImg;} // end of getFrame() getFrame()和closeMovie()方法在JMFSnapper中是同步的.closeMovie()中止播放器,在任何時間都可能被調用.同步關鍵字確保當幀從動畫中被抽取時播放器不會被關閉. formatImg BufferedImage對象在JMFSnapper構造器中初始化:formatImg = new BufferedImage( FORMAT_SIZE, FORMAT_SIZE, BufferedImage.TYPE_3BYTE_BGR);6. 另一種抓圖方案 Sun公司的JMF實例網點提供了另外兩種抽取幀方法.VideoRendererDemoJMFJ3D實例由Java 3D和JMF應用程序組成,它展示了怎樣將一個視頻環繞一個主體.Java 3D與我討論的一些東西-使用 BufferedImage.TYPE_3BYTE_BGR格式的BufferedImage傳遞給ImageComponent2D對象,然后變為柱面圖像-在本質上是相同的.這個圖像也使用BufferedImage.TYPE_4BYTE_ABGR格式,此格式是Solaris要求的以便符合提及的圖像格式.這個程序的JMF與我們的相當不同.一個JMF的VideoRenderer應用程序接口是附加在TrackControl對象,此對象是控制動畫的視頻軌跡.一旦TrackControl對象被喚醒,VideoRenderer的process()方法被自動調用以便適用視頻中的每一個幀.process()的輸入是Buffer對象.勝于我曾描述的Buffer-to-BufferedImage轉換步驟,DemoJMFJ3D以低水準構建BufferedImage,BufferedImage的像素化圖像和Buffer原始數據時間的比特數組拷貝.3D聊天室實例中的DemoJMFJ3D編碼盡在Java Media APIs: Cross-Platform Imaging, Media and Visualization,A. Terrazas, J. Ostuni和M. Barlow所著.這本書是對于JMF是本很好的入門書籍,其中也有很多關于Java 3D的有趣篇章.Processor Codec插件FrameAccess實例使用很多更先進的JMF元素,以Processor codec插件為中心.Processor類是Player的一個延伸版本,它對于媒體數據處理有更強的能力.一個多媒體數字信號編解碼器插件能夠從一段軌跡中讀取幀,以任意方式處理它們,然后將他們寫回軌跡.Codec的process()方法中,提供其一個含有輸入幀的Buffer對象,空Buffer對象輸出.FrameAccess附加一個Codec插件以訪問動畫的視頻軌跡,使用輸入幀Buffer對象傳遞給process()方法以產生一些關于視頻的基本統計表.這個實例易于改進以便將Buffer對象轉化為BufferedImage,任意使用我的方法或者DemoJMFJ3D的比特數組技術.不幸的是,Processor類不能用來支持插件;結果,插件在JMF 1.0或2.0-based版本下不能工作.在使用Sun公司的JMF實例前尋找jmf-interest mailing list是一個不錯的注意,因為大多數的程序在各種版本的JMF下都存在問題. Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
標簽: Java
相關文章:
主站蜘蛛池模板: 欧美在线香蕉在线现视频 | 精品久久久久久无码中文字幕 | 国产午夜精品理论片影院 | 日韩字幕一中文在线综合 | 亚洲悠悠色综合中文字幕 | 亚洲国产成人久久综合区 | 91香蕉国产观看免费人人 | 国产精品亚洲二区 | 成人黄色免费网址 | 毛片免费视频网站 | 男女扒开双腿猛进入免费网站 | 一级片a级片 | 99精彩免费观看 | 欧美一级片免费 | 欧美成人性色生活片天天看 | 久久久欧美综合久久久久 | 国产r67194吃奶视频 | 性做久久久久免费观看 | 天天操夜夜噜 | 国产爽的冒白浆的视频高清 | 成人夜色视频网站在线观看 | 国产成人精品高清免费 | 久久精品免费视频观看 | 免费观看欧美一级牲片一 | 久久免费国产精品一区二区 | 欧美一级aa免费毛片 | 欧美一级精品高清在线观看 | 日本加勒比一区 | 亚洲一级毛片免费在线观看 | 亚洲一区 欧美 | 自拍成人 | 色樱桃影院亚洲精品影院 | 99这里只有精品66视频 | 久久高清免费 | 日本免费三级网站 | pgone太大了兽王免费视频 | 日本特级视频 | 国产盗摄一区二区三区 | 亚欧视频在线观看 | 日韩一区二区三区精品 | 国产成人一区二区三中文 |