时间隔了很久了,终于更新了。这篇文章将继续介绍Papervision3D 中如何进行其他材质的贴图,在之前的系列中主要以增加3D场景的真实性为目的,这篇文章则要把重点放在如何给场景添加更多的动态可能性。
首先,抱歉这篇文章可能有点长,这篇里要讲的主要是MovieMaterials 动画贴图材质和VideoStreamMaterial 影片贴图材质,它们能通过使用Flash movies 或者 Flash video streams 来给3D物体表面提供动动画效果和增加交互可能性。其实把这些内容总结成几条来描述Papervision3D 能提供的可能性也许不公平,所以我试着描述的更广泛一点,但是即使这样做了我想仍然会丢失很多东西。可能性更多取决于使用人的创造力。
MovieMaterial 动画贴图材质允许我们使用一个已经存在的flash动画文件或者任何在库中导出过的MovieClip、Sprite 为贴图材质。Papervision3D 能将他们映射到3D物体的表面,并且允许我们直接在3D 场景上和动画里的内容进行交互,比如鼠标点击,移动这类的。
VideoStreamMaterial 影片贴图材质则就像他的名字描述的那样,允许我们使用一段flv 影片贴图在3D 物体的表面。
下面的例子会包含3种可行性的应用:一是使用一个2D flash movie为贴图材质并允许和里面进行交互,二是使用一段影片为贴图材质,三是使用另一个Papervision3D flash movie为贴图材质并允许和里面的3D 内容进行交互。
所以这篇文章会涉及到3个Actionscript classes:一个3D主场景,一个2D flash movie 和另一个Papervision3D flash movie,这里会讨论第一个并在文章结尾处付上其他源文件。
下面的源代码会实现3个被不同材质贴过图后的平板围绕的y轴转动,这些平板能通过双击使其固定并进行放大,以便你更方便和平板上的内容进行交互,再双击可以使其归位。整个场景可以通过背景上按住鼠标左键后移动鼠标来调整摄象机位置角度。整段代码有点长,但是我仍然会对每一段进行解释。虽然看上去长,但是相信我其实一点也不复杂。这个例子里仍然使用Tweener 来获得更好的运动效果,之前介绍过Tweener 的。
package {
import caurina.transitions.Tweener;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.materials.VideoStreamMaterial;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
[SWF(backgroundColor="#222222")]
public class Example008 extends BasicView {
private static const ORBITAL_RADIUS:Number = 400;
[Embed(source="/../assets/DrawTool.swf")]
private var DrawTool:Class;
private var exampleMovie:MovieClip;
private var videoURL:String = "http://www.tartiflop.com/pv3d/FirstSteps/Radiohead_HOC.flv";
private var video:Video;
private var stream:NetStream;
private var connection:NetConnection;
private var objectGroup:DisplayObject3D;
private var light:PointLight3D;
private var currentActiveObject:DisplayObject3D = null;
private var projectors:Array = new Array();
private var doRotation:Boolean = false;
private var canRotate:Boolean = true;
private var lastMouseX:int;
private var lastMouseY:int;
private var cameraPitch:Number = 60;
private var cameraYaw:Number = -60;
public function Example008() {
super(0, 0, true, true);
// Initialise Papervision3D
init3D();
// create video stream for VideoStreamMaterial
createVideoStream();
// create the 3D Objects
createScene();
// Listen to mouse up and down events on the stage
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
// Start rendering the scene
startRendering();
}
private function init3D():void {
// position the camera
camera.z = -1000;
camera.fov = 60;
camera.orbit(cameraPitch, cameraYaw);
}
private function createVideoStream():void {
// Create a NetConnection. 2-way connection not necessary: connect to null
connection = new NetConnection();
connection.connect(null);
// Create a new NetStream to obtain the flv stream. Ignore client messages so use a simple Object
stream = new NetStream(connection);
stream.client = new Object();
// create a new video player
video = new Video();
// start streaming the video from the given URL and play it on the video player
stream.play(videoURL);
video.attachNetStream(stream);
}
private function createScene():void {
// Specify a point light source and its location
light = new PointLight3D();
light.x = 400;
light.y = 1000;
light.z = -400;
// Create a 3D object to group the projectors
objectGroup = new DisplayObject3D();
// Create a new video stream material with precise rendering.
var videoMaterial:VideoStreamMaterial = new VideoStreamMaterial(video, stream, true);
addProjector(videoMaterial);
// Create a new flash movie material from an actionscript class (not transparent, animated and precise rendering)
var movieMaterial1:MovieMaterial = new MovieMaterial(new Example006b(), false, true, true);
addProjector(movieMaterial1);
// Create a new flash movie material from an embedded flash movie (not transparent, animated and precise rendering)
var movieMaterial2:MovieMaterial = new MovieMaterial(new DrawTool(), false, true, true);
addProjector(movieMaterial2);
// add the object group and light
scene.addChild(objectGroup);
scene.addChild(light);
// set up the projector positions in the scene
organiseProjectors();
}
private function addProjector(material:MovieMaterial):void {
// materials are smooth rendred, interactive and resize to the 3D object.
material.smooth = true;
material.interactive = true;
material.allowAutoResize = true;
// simple flat shaded material as default for the projector
var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterial(light, 0x554D33, 0x1A120C);
flatShadedMaterial.interactive = true;
// Material list with MovieMaterial used on the front, the rest being flat shaded
var materialList:MaterialsList = new MaterialsList({"all":flatShadedMaterial, "front":material});
// create a new interactive projector
var projector:Cube = new Cube(materialList, 320, 10, 240);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_DOUBLE_CLICK, onMouseDoubleClickOnObject);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, onMouseOverObject);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, onMouseOutObject);
// add the projector to the scene, being part of the object group
objectGroup.addChild(projector);
// store projector in an array
projectors.push(projector);
}
private function organiseProjectors():void {
// calculate angle between projectors
var theta:Number = 360 / projectors.length;
// set up each projector so that they are distributed in a circle and facing outwards
for (var i:int = 0; i < projectors.length; i++) {
var projector:Cube = projectors[i];
// specifc angle for projector
var angle:Number = i * theta - 180;
var angleRadians:Number = angle * 2 * Math.PI / 360.;
// position of projector
var x:Number = Math.sin(angleRadians) * ORBITAL_RADIUS;
var z:Number = Math.cos(angleRadians) * ORBITAL_RADIUS;
// create tween to position, rotate and scale projector smoothly over 1 second
Tweener.addTween(projector, {x:x, y:-150, z:z, rotationY:angle, scale:0.8, time:1, transition:"linear" });
}
}
override protected function onRenderTick(event:Event=null):void {
// rotate the object group: angle kept between 0 and 360 degrees
objectGroup.rotationY += 1;
if (objectGroup.rotationY > 360) {
objectGroup.rotationY -= 360;
}
// if an object is active (double clicked) rotate it in the opposite direction
// to the group so that it is stationary
if (currentActiveObject != null) {
currentActiveObject.rotationY -=1;
if (currentActiveObject.rotationY < 0) {
currentActiveObject.rotationY += 360;
}
}
// If the mouse button has been clicked then update the camera position
if (doRotation && canRotate) {
// convert the change in mouse position into a change in camera angle
var dPitch:Number = (mouseY - lastMouseY) / 2;
var dYaw:Number = (mouseX - lastMouseX) / 2;
// update the camera angles
cameraPitch -= dPitch;
cameraYaw -= dYaw;
// limit the pitch of the camera
if (cameraPitch <= 0) {
cameraPitch = 0.1;
} else if (cameraPitch >= 180) {
cameraPitch = 179.9;
}
// reset the last mouse position
lastMouseX = mouseX;
lastMouseY = mouseY;
// reposition the camera
camera.orbit(cameraPitch, cameraYaw);
}
// call the renderer
super.onRenderTick(event);
}
// called when mouse down on stage
private function onMouseDown(event:MouseEvent):void {
doRotation = true;
lastMouseX = event.stageX;
lastMouseY = event.stageY;
}
// called when mouse up on stage
private function onMouseUp(event:MouseEvent):void {
doRotation = false;
}
// called when mouse double clicked on a projector
private function onMouseDoubleClickOnObject(event:InteractiveScene3DEvent):void {
var object:DisplayObject3D = event.displayObject3D;
// determine if the object is to be activated (placed in center) or deactivated
if (object == currentActiveObject) {
deactivate(object);
} else {
activate(object);
}
}
// disable camera rotation when mouse is over a projector
private function onMouseOverObject(event:InteractiveScene3DEvent):void {
canRotate = false;
}
// re-enable camera rotation when mouse is out of a projector
private function onMouseOutObject(event:InteractiveScene3DEvent):void {
canRotate = true;
}
// places a projector in the center
private function activate(object:DisplayObject3D):void {
// remove projector from rotating projectors array
projectors.splice(projectors.indexOf(object), 1);
// if a projector is active already, put it back in the array of rotating projectors
if (currentActiveObject != null) {
projectors.push(currentActiveObject);
}
// create a tween to place selected projector in the center
Tweener.addTween(object, {y:100, x:0, z:0, rotationY:-objectGroup.rotationY, scale:2, time:1, transition:"linear" });
currentActiveObject = object;
// re-organise the other projectors
organiseProjectors();
}
// puts an activated projector back into the main pack of rotating projectors
private function deactivate(object:DisplayObject3D):void {
// put the projector back into the rotating projectors array
projectors.push(currentActiveObject);
currentActiveObject = null;
// re-organise all projectors
organiseProjectors();
}
}
}
OK,就像这个系列的前几篇文章一样,我们通常是拿前面的例子修改以便更容易理解,而在这个例子里修改主要来自为影片创建影片贴图和更改场景的交互方式,下面我们一步一步来看。
让我们从构造函数开始,可以发现唯一的不同就是新加了播放flv影片的初始化过程,而且在flash中播放flv影片可以是一个纯as工作,所以不需要借助任何其他东西。
private function createVideoStream():void {
// Create a NetConnection. 2-way connection not necessary: connect to null
connection = new NetConnection();
connection.connect(null);
// Create a new NetStream to obtain the flv stream. Ignore client messages so use a simple Object
stream = new NetStream(connection);
stream.client = new Object();
// create a new video player
video = new Video();
// start streaming the video from the given URL and play it on the video player
stream.play(localVideoURL);
video.attachNetStream(stream);
}
下面看场景构造方法createScene ,因为是用前面的例子修改而来,所以保留了光源,做了一个object group 把3个平板放在里面模拟转动。
private function createScene():void {
// Specify a point light source and its location
light = new PointLight3D();
light.x = 400;
light.y = 1000;
light.z = -400;
// Create a 3D object to group the projectors
objectGroup = new DisplayObject3D();
// Create a new video stream material with precise rendering.
var videoMaterial:VideoStreamMaterial = new VideoStreamMaterial(video, stream, true);
addProjector(videoMaterial);
// Create a new flash movie material from an actionscript class (not transparent, animated and precise rendering)
var movieMaterial1:MovieMaterial = new MovieMaterial(new Example006b(), false, true, true);
addProjector(movieMaterial1);
// Create a new flash movie material from an embedded flash movie (not transparent, animated and precise rendering)
var movieMaterial2:MovieMaterial = new MovieMaterial(new DrawTool(), false, true, true);
addProjector(movieMaterial2);
// add the object group and light
scene.addChild(objectGroup);
scene.addChild(light);
// set up the projector positions in the scene
organiseProjectors();
}
看了上面3个MovieMaterial (VideoStreamMaterial 继承自MovieMaterial )的个实例化发现很简单吧。对于MovieMaterial 最后3个布尔值分别表示透明,播放动画和精确渲染。所以如果你需要贴图用的flash movie是动态的,就设置播放动画为true。
贴图材质做好了要将他贴给3D Object,在上面使用了addProjector 函数,因为每个贴图的使用步骤都一样,所以使用一个函数来做节省了多代码。
private function addProjector(material:MovieMaterial):void {
// materials are smooth rendred, interactive and resize to the 3D object.
material.smooth = true;
material.interactive = true;
material.allowAutoResize = true;
// simple flat shaded material as default for the projector
var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterial(light, 0x554D33, 0x1A120C);
flatShadedMaterial.interactive = true;
// Material list with MovieMaterial used on the front, the rest being flat shaded
var materialList:MaterialsList = new MaterialsList({"all":flatShadedMaterial, "front":material});
// create a new interactive projector
var projector:Cube = new Cube(materialList, 320, 10, 240);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_DOUBLE_CLICK, onMouseDoubleClickOnObject);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, onMouseOverObject);
projector.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, onMouseOutObject);
// add the projector to the scene, being part of the object group
objectGroup.addChild(projector);
// store projector in an array
projectors.push(projector);
}
每一个MovieMaterial 都设置允许平滑,允许交互,允许自动适应尺寸。然后实例化一个MaterialsList 来给Cube(平板是用cube模拟的) 贴图,Cube 5个面都使用FlatShadeMaterial ,front面则使用MovieMaterial 。然后给Cube 加上监听函数,这样就可是响应在Cube 身上的双击事件之类的了。这3个平板之后都加入objectGroup群组,再储存在projectors数组里,以便后面访问时调用。
在上面场景构造最后看到一个organiseProjectors 函数是用来设置这3个平板的坐标位置的。
private function organiseProjectors():void {
// calculate angle between projectors
var theta:Number = 360 / projectors.length;
// set up each projector so that they are distributed in a circle and facing outwards
for (var i:int = 0; i < projectors.length; i++) {
var projector:Cube = projectors[i];
// specifc angle for projector
var angle:Number = i * theta - 180;
var angleRadians:Number = angle * 2 * Math.PI / 360.;
// position of projector
var x:Number = Math.sin(angleRadians) * ORBITAL_RADIUS;
var z:Number = Math.cos(angleRadians) * ORBITAL_RADIUS;
// create tween to position, rotate and scale projector smoothly over 1 second
Tweener.addTween(projector, {x:x, y:-150, z:z, rotationY:angle, scale:0.8, time:1, transition:"linear" });
}
}
这个函数通过一个for循环给每个平板计算分配了自己的角度和位置,并使用了Tweener 让这些平板在开始的时候运动到自己该处的位置。
下面的onRenderTick 则用来描述整个flash在每个frame该做什么事情。
override protected function onRenderTick(event:Event=null):void {
// rotate the object group: angle kept between 0 and 360 degrees
objectGroup.rotationY += 1;
if (objectGroup.rotationY > 360) {
objectGroup.rotationY -= 360;
}
// if an object is active (double clicked) rotate it in the opposite direction
// to the group so that it is stationary
if (currentActiveObject != null) {
currentActiveObject.rotationY -=1;
if (currentActiveObject.rotationY < 0) {
currentActiveObject.rotationY += 360;
}
}
// If the mouse button has been clicked then update the camera position
if (doRotation && canRotate) {
// convert the change in mouse position into a change in camera angle
var dPitch:Number = (mouseY - lastMouseY) / 2;
var dYaw:Number = (mouseX - lastMouseX) / 2;
// update the camera angles
cameraPitch -= dPitch;
cameraYaw -= dYaw;
// limit the pitch of the camera
if (cameraPitch <= 0) {
cameraPitch = 0.1;
} else if (cameraPitch >= 180) {
cameraPitch = 179.9;
}
// reset the last mouse position
lastMouseX = mouseX;
lastMouseY = mouseY;
// reposition the camera
camera.orbit(cameraPitch, cameraYaw);
}
// call the renderer
super.onRenderTick(event);
}
这里的object group群组转动在前面的例子中也使用过,但是这次我用了控制rotationY 属性的方式而不是使用yaw 函数,因为这样做对位置的精确控制会更加方便。
再下面的代码就是定义onMouseDown, onMouseUp 事件了。这些是用来配合鼠标控制摄象机的,和之前的例子一样就不多将了。新加的onMouseOverObject 和 onMouseOutObject 也是配合控制摄象机的。
主要讲一讲onMouseDoubleClickOnObject 双击事件。
// called when mouse double clicked on a projector
private function onMouseDoubleClickOnObject(event:InteractiveScene3DEvent):void {
var object:DisplayObject3D = event.displayObject3D;
// determine if the object is to be activated (placed in center) or deactivated
if (object == currentActiveObject) {
deactivate(object);
} else {
activate(object);
}
}
如何我们双击一个物体则将它设置为currentActiveObject,如果再双击她则取消设置。
// places a projector in the center
private function activate(object:DisplayObject3D):void {
// remove projector from rotating projectors array
projectors.splice(projectors.indexOf(object), 1);
// if a projector is active already, put it back in the array of rotating projectors
if (currentActiveObject != null) {
projectors.push(currentActiveObject);
}
// create a tween to place selected projector in the center
Tweener.addTween(object, {y:100, x:0, z:0, rotationY:-objectGroup.rotationY, scale:2, time:1, transition:"linear" });
currentActiveObject = object;
// re-organise the other projectors
organiseProjectors();
}
// puts an activated projector back into the main pack of rotating projectors
private function deactivate(object:DisplayObject3D):void {
// put the projector back into the rotating projectors array
projectors.push(currentActiveObject);
currentActiveObject = null;
// re-organise all projectors
organiseProjectors();
}
这里的activate 和deactivate 函数,用来设置平板处于双击放大状态和再次双击归位时候的位置设置。
这篇文章到这里就结束了,在这里例子可是发现当使用了Papervision3D 和 Tweener 在一起工作时候,生成了效果很棒3D动画。再配合了movie materials 发现这个世界又不可思义了,而这一切我们所做的工作并不多,Papervision3D 给我们安排好了一些。其实很感谢Papervision3D 作者们的工作。
最后 drawTool.as :
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class DrawTool extends Sprite {
private var isDrawing:Boolean = false;
public function DrawTool() {
// create a drawing surface
graphics.beginFill(0xEEEEEE);
graphics.moveTo(0, 0);
graphics.lineTo(320, 0);
graphics.lineTo(320, 240);
graphics.lineTo(0, 240);
graphics.endFill();
// create text and format
var textFormat:TextFormat = new TextFormat();
textFormat.size = 30;
textFormat.font = "Arial";
var text:TextField = new TextField();
text.x = 50;
text.y = 100;
text.textColor = 0x222222;
text.text = "click to draw!";
text.setTextFormat(textFormat);
text.autoSize = TextFieldAutoSize.LEFT;
text.selectable = false;
addChild(text);
// listen to mouse events
this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
// start drawing circles
private function onMouseDown(event:MouseEvent):void {
isDrawing = true;
drawCircle(event.stageX, event.stageY);
}
// stop drawing circles
private function onMouseUp(event:MouseEvent):void {
isDrawing = false;
}
// draw a circle
private function onMouseMove(event:MouseEvent):void {
if (isDrawing) {
drawCircle(event.stageX, event.stageY);
}
}
// circle drawing function
private function drawCircle(x:int, y:int):void {
graphics.beginFill(Math.random() * 0xFFFFFF, 0.5);
graphics.drawCircle(x, y, 5);
graphics.endFill();
}
}
}
还有Example006b.as :
package {
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;
[SWF(backgroundColor="#FFFFFF")]
public class Example006b extends BasicView {
[Embed(source="/../assets/pv3d.png")] private var PV3D:Class;
private static const ORBITAL_RADIUS:Number = 100;
private var bitmap:Bitmap = new PV3D();
private var cube1:Cube;
private var cube2:Cube;
private var sphere1:Sphere;
private var sphere2:Sphere;
private var objectGroup:DisplayObject3D;
private var doRotation:Boolean = false;
private var lastMouseX:int;
private var lastMouseY:int;
private var cameraPitch:Number = 60;
private var cameraYaw:Number = -60;
public function Example006b() {
var background:Sprite = new Sprite();
background.graphics.beginFill(0x000000);
background.graphics.moveTo(0, 0);
background.graphics.lineTo(320, 0);
background.graphics.lineTo(320, 240);
background.graphics.lineTo(0, 240);
background.graphics.endFill();
addChild(background);
super(320, 240, true, false);
// Initialise Papervision3D
init3D();
// Create the 3D objects
createScene();
// Listen to mouse up and down events on the stage
background.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
background.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
background.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
// Start rendering the scene
startRendering();
}
private function init3D():void {
// position the camera
camera.z = -500;
camera.orbit(cameraPitch, cameraYaw);
}
private function createScene():void {
// create interactive bitmap material
var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, false);
// create an interactive tiled bitmap material (bitmap tiled as 2 x 2)
var tiledBitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, false);
tiledBitmapMaterial.tiled = true;
tiledBitmapMaterial.maxU = 2;
tiledBitmapMaterial.maxV = 2;
// create cube with simple bitmap material
cube1 = new Cube(getBitmapMaterials(bitmapMaterial), 50, 50, 50);
cube1.x = ORBITAL_RADIUS;
// create cube with tiled bitmap material
cube2 = new Cube(getBitmapMaterials(tiledBitmapMaterial), 50, 50, 50);
cube2.x = -ORBITAL_RADIUS;
// create sphere with simple bitmap material
sphere1 = new Sphere(bitmapMaterial, 25, 10, 10);
sphere1.z = ORBITAL_RADIUS;
// create sphere with tiled bitmap material
sphere2 = new Sphere(tiledBitmapMaterial, 25, 10, 10);
sphere2.z = -ORBITAL_RADIUS;
// Create a 3D object to group the spheres
objectGroup = new DisplayObject3D();
objectGroup.addChild(cube1);
objectGroup.addChild(cube2);
objectGroup.addChild(sphere1);
objectGroup.addChild(sphere2);
// Add the light and spheres to the scene
scene.addChild(objectGroup);
}
private function getBitmapMaterials(bitmapMaterial:BitmapMaterial):MaterialsList {
// create list of materials for all faces of the cube,
// all with the same bitmap material
var materials:MaterialsList = new MaterialsList();
materials.addMaterial(bitmapMaterial, "all");
return materials;
}
override protected function onRenderTick(event:Event=null):void {
// rotate the objects
cube1.yaw(-3);
cube2.yaw(-3);
sphere1.yaw(-3);
sphere2.yaw(-3);
// rotate the group of objects
objectGroup.yaw(1);
// call the renderer
super.onRenderTick(event);
}
// called when mouse down on stage
public function onMouseDown(event:MouseEvent):void {
doRotation = true;
lastMouseX = event.stageX;
lastMouseY = event.stageY;
}
// called when mouse up on stage
public function onMouseUp(event:MouseEvent):void {
doRotation = false;
}
// called when the mouse moves over the stage
public function onMouseMove(event:MouseEvent):void {
// If the mouse button has been clicked then update the camera position
if (doRotation) {
// convert the change in mouse position into a change in camera angle
var dPitch:Number = (event.stageY - lastMouseY) / 2;
var dYaw:Number = (event.stageX - lastMouseX) / 2;
// update the camera angles
cameraPitch -= dPitch;
cameraYaw -= dYaw;
// limit the pitch of the camera
if (cameraPitch < = 0) {
cameraPitch = 0.1;
} else if (cameraPitch >= 180) {
cameraPitch = 179.9;
}
// reset the last mouse position
lastMouseX = event.stageX;
lastMouseY = event.stageY;
// reposition the camera
camera.orbit(cameraPitch, cameraYaw);
}
}
}
}

写的很好,受益非浅
很好, 很强, 很..
期待你写一篇关于PV3D导入外部模型的文章!
“欢迎加入QQ讨论群:6707329″ ,加入时提示已满。
太强了。
不过我还有一些问题,我想做一个驾车的游戏,我觉得最大的问题是三个反光镜怎么做,不知道有没有类似3DMax中的镜面贴图,或加几个摄像机也行。
其次是要加一个车模进来,要从里面看外面,这些应该好办一些。
QQ:107959088
email:hhhh_63@hotmail.com
这是我的联系方式,不知道能不能请你帮做这个项目。
谢谢
请问如何 对 ASE 模型贴图呢?还有 DAE 模型是那么建立呢?导入的模型是 多面体 还有 曲面 请问 如何贴图啊?问题多多啊。我能控制模型的各个节点不呢 ?
请教一下,代码在CS4上可以通过,在CS3上却总是报错,怎么解决?谢谢!
请问能不能把网页内容以贴上去呢?
如果能,那支持和网页的交互么?