分享
 
 
 

JAVA3D动画展示图(Part2,使用QuickTime)

王朝java/jsp·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

在这一系列的第一部分中,我描述了在JMF(JAVA媒体帧工作器 下同)的帮助下,怎样将一部电影片断插入JAVA 3D场景中。这个执行过程使用Model-View-Controller设计模式。

。动画屏幕是由JMFMovieScreen类表示的视觉元素

。动画模型部分由JMFSnapper类控制

。java 3D行为类,TimeBehavior,是动画中引起帧周期性恢复的控制类

在这篇文章中,我将使用QTJ(QuickTime for Java 下同)再次解析动画成份。QTJ提供一个覆盖QuickTime API的依赖对象的java,使之可以展示,编辑和创建QuickTime动画;捕获视频 音频;展示2D和3D动画。QuickTime可用于Mac和Windows系统。关于QTJ的安装.文档和实例细节可在developer.apple.com/quicktime/qtjava查询。

由设计模式作出的推论,只在动画类JMFSnapper被QTSnapper取代时,QTJ取代JMF在应用中有微小的作用。

图1:两幅QTJ情况下的3D动画截屏,右边图片采取显示屏背面视角

从图1大致看出,QTJ-based 和JMF成像效果没有明显区别。

然而,通过更仔细得比较可以看出有两个变化:QTJ动画有轻微的被像素化,播放的更慢。像素化(像素化是对内部像素对于观看者易见的数字图像的显示。当一些用于普通的计算机显示的低分辨率图像被投射到一个大的显示器上,每一个像素都会变得单独可见,这种不常发生的现象就叫做像素化。)是由于原始动画从MPEG转换为QuickTime's MOV格式引起的,它可由更好的转换方法矫正。速度问题更基础:它与QTSnapper的潜在执行有关。

这篇文章的重点为?

。执行QTSnapper的两种主要方法的讨论.一种方法是将动画里的每一帧都提出来显示在屏幕上。另一种方法依靠当前的时间提出帧.第二种方法意味着可能将会遗漏部分帧,画面颤抖,但遗漏 可以使播放更快

。一些简单的FPS(frame-per-second)度量器的介绍.我将用它们这两种方法的相对速度,探测遗漏帧数

1. 此山非彼山

与第一部分一样,编码将利用两个大型的API,在这里没有时间介绍利用的细节了。我将再次使用java 3D,但API媒体将由JMF转变为QTJ。

在我的O'Reilly book, Killer Game Programming in Java (KGPJ)中有大量关于java 3D的信息,还有图1的原码。

我将不会解释动画屏幕和动画更新行为,因为它们与第一部分相同。

在QTJ技术中我将会使用QTSnapper从动画中提取帧

2.应用的两种看法

图2:应用流程图

此图表与第一篇文章中的几乎相同

QuickTime动画由QTSnapper类加载,动画屏幕由QTMovieScreen创建.每40毫秒,TimeBehavior对象调用QTMovieScreen中的nextFrame()方法.然后调用QTSnapper中的getFrame()方法获取动画中的一个帧.依次循环.

JMFSnapper与QTSnapper之间有一个很重要的不同.JMFSnapper返回一个帧,这个帧是动画播放时的当前帧.而QTSnapper返回动画中的帧根据递增的索引.

例如.当getFrame()方法在JMFSnapper被反复调用时,也许会重新得到帧1,3,6,9等等,它是由方法何时被调用与动画播放速度决定的.当getFrame()方法在QTSnapper被调用,它将会返回帧1,2,3,4等等.

图3:UML类的应用图表,仅列出公共方法.

此图表除了动画屏幕名和动画类名(QTMovieScreen 和 QTSnapper)外,与第一篇文章的相同.事实上,只有Snapper类的内部执行被改变.

JMF Movie3D应用程序和QTJ-based版本之间的改动需要Snapper被重写.

// global variableprivate QTSnapper snapper;

// was JMFSnapper// in the constructor, load the movie in fnmsnapper = new QTSnapper(fnm);

这两处改动是由于须将JMFMovieScreen重命名为QTMovieScreen.

这个例子中的所有代码,和文章的早期版本,可以在KGPJ website查询到.

3.一帧一帧的动画

理解QTSnapper的内在工作机理,可以帮助我们对QuickTime动画构造有一个大致的认识.每一幅动画可以理解为视频轨迹和音频轨迹在相同时间上的重叠.图4是这种思想的图示

图4:QuickTime动画的内部构造机理

每个轨迹控制着其自身数据,例如它包含的媒体类型和媒体本身.媒体容器(media container)有它自己的数据结构,包括它的持续时间和播放率(每秒播放抽样数).媒体是由一组抽样(或帧)组成,第一个抽样时间为0(与媒体时间有关).抽样是被变址的,第一个抽样在1位置(非0).

图5大致描述了QuickTime的轨迹和媒体结构

图5:QuickTime轨迹和媒体的内在构造机理

想要得到更多信息,请查询QuickTime指南的movie section

打开动画视频媒体

QTSnapper构造器打开动画:

// globalsprivate boolean isSessionOpen = false;private OpenMovieFile movieFile;private Movie movie;// in the constructor,// start a QuickTime sessionQTSession.open();isSessionOpen = true;// open the moviemovieFile =

OpenMovieFile.asRead( new QTFile(fnm) );movie = Movie.fromFile(movieFile);

在QuickTime使用之前调用QTSession.open()方法将其初始化.在终止时相应的调用QTSession.close()方法.

轨迹定位和媒体访问

// more globalsprivate Track videoTrack;private Media vidMedia;// in the constructor, // extract the video track from the movievideoTrack =

movie.getIndTrackType(1,

StdQTConstants.videoMediaType,

StdQTConstants.movieTrackMediaType);if (videoTrack == null) {

System.out.println("Sorry, not a video");

System.exit(0);}// get the media used by the video trackvidMedia = videoTrack.getMedia();

一旦媒体打开,从中提取各种信息

// more globalsprivate MediaSample mediaSample;private int numSamples;

// number of samplesprivate int sampIdx;

// current sample indexprivate int width;

// frame widthprivate int height;

// frame height// in the constructornumSamples = vidMedia.getSampleCount();sampIdx = 1;

// get first sample in the trackmediaSample = vidMedia.getSample(0,

vidMedia.sampleNumToMediaTime(sampIdx).time,1);// store width and height of image in the sampleImageDescription imgDesc =

ImageDescription) mediaSample.description;width = imgDesc.getWidth();height = imgDesc.getHeight();

sampIdx作为计数器将在抽样中被重复调用(抽样于位置1开始).

动画图像的宽度和高度由第一个抽样获得,接下来所有的抽样都是同样的尺寸.

测算 FPS

由QTSnapper返回的 帧数/秒 将在稍后被用作类的不同使用方法的比较参数.构造器中必要的参数已被初始化.

// frame rate globalsprivate long startTime;private long numFramesMade;// initialize them in the constructorstartTime = System.currentTimeMillis(); numFramesMade = 0;

结束

将应用程序结束时,QTSnapper类中的stopMovie()方法将被调用.它报告FPS,关闭QuickTime.

// globalsprivate DecimalFormat frameDf =

new DecimalFormat("0.#"); // 1 dpsynchronized public void stopMovie(){

if (isSessionOpen) {

// report frame rate

long duration =

System.currentTimeMillis() - startTime;

double frameRate =

((double) numFramesMade*1000.0)/duration;

System.out.println("FPS: " +

frameDf.format(frameRate));

QTSession.close();

// close down QuickTime

isSessionOpen = false;

}}

由于stopMovie()和getFrame()是同步的,所以从动画中提取帧和QuickTime关闭在时间上是不可能同时进行.

缓存帧

getFrame()返回一次抽样样品,称作BufferedImage对象.被选择的帧利用索引指数存贮在sampIdx.

// globalsprivate BufferedImage img, formatImg;synchronized public BufferedImage getFrame(){

if (!isSessionOpen)

return null;

if (sampIdx numSamples)

// start back with the first sample

sampIdx = 1;

try {

/* Get the sample starting at the

specified index time */

TimeInfo ti =

vidMedia.sampleNumToMediaTime(sampIdx);

mediaSample=vidMedia.getSample(0,ti.time,1);

sampIdx++;

writeToBufferedImage(mediaSample, img);

// resize img, writing it to formatImg

Graphics g = formatImg.getGraphics();

g.drawImage(img, 0, 0,

FORMAT_SIZE, FORMAT_SIZE, null);

// Overlay current t

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有