查看: 2320|回复: 1
打印 上一主题 下一主题

[Sandy3D] sandy3d---World3D.as

[复制链接]

46

主题

0

听众

630

积分

初级设计师

Rank: 3Rank: 3

纳金币
386
精华
8

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2013-12-5 14:03:50 |只看该作者 |倒序浏览
/*
# ***** BEGIN LICENSE BLOCK *****
Copyright the original author or authors.
Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# ***** END LICENSE BLOCK *****
*/
import com.bourre.commands.Delegate;
import com.bourre.events.BasicEvent;
import com.bourre.events.EventBroadcaster;
import com.bourre.events.EventType;
import com.bourre.transitions.FpsBeacon;
import sandy.core.data.Vertex;
import sandy.core.data.Vector;
import sandy.core.data.Matrix4;
import sandy.core.group.Group;
import sandy.core.group.Node;
import sandy.core.group.INode;
import sandy.core.buffer.ZBuffer;
import sandy.core.buffer.MatrixBuffer;
import sandy.view.Camera3D;
import sandy.view.IScreen;
import sandy.core.light.Light3D;
import sandy.core.Object3D;

/**
* The 3D world for displaying the Objects.用于显示物体的3维世界
* <p>World3D is a singleton class, it's the central point of Sandy :
* <br/>You can have only one World3D, which contain Groups, Cameras and Lights</p>
* 你只能拥有一个World3D,用于容纳组员,摄影机和灯光。
* @author  Thomas Pfeiffer - kiroukou
* @版本  1.0
* @date   16.05.2006
* @see   sandy.core.Object3D
*
**/
class sandy.core.World3D
{
/**
  * world3d渲染事件,它就是每次渲染场景所播报的事件。The World3D rendering Event. It's the event broadcasted every time the world is rendered
  */
public static var onRenderEVENT:EventType   = new EventType( 'onRender' );
/**
  * World3D起始事件,当开始渲染场景时播报。The World3D start Event. Broadcasted when the world start to be rendered
  */
public static var onStartEVENT:EventType   = new EventType( 'onStart' );
/**
  * World3D停止事件,每当停止渲染场景时播报。The World3D stop Event. Broadcasted when the world stop to be rendered
  */
public static var onStopEVENT:EventType   = new EventType( 'onStop' );
/**
  * World3D灯光更改事件,当灯光改变时播报。The World3D onLightUpdated Event. Broadcasted when the world light is changed
  */
public static var onLightUpdatedEVENT:EventType = new EventType( 'onLightUpdated' );
/**
  * The World3D onLightUpdated Event. Broadcasted when the world light is changed
  */
public static var onInitCacheEVENT:EventType  = new EventType( 'onInitCache' );


/**
  *私有构造函数 Private Constructor.
  *
  * <p>只能有一个World3D。You can have only one World3D</p>
  *
  */
private function World3D ()
{
  _eRender  = new BasicEvent( World3D.onRenderEVENT );
  _eStart  = new BasicEvent( World3D.onStartEVENT );
  // 初始化事件广播器。init the event broadcaster
  _oEB = new EventBroadcaster( this );
  //缺省灯光 default light
  _light = new Light3D( new Vector( 0, 0, 1 ), 50 );
  _isRunning = false;
  _aCams = [];
  // 添加侦听器we add the listener
  FPSBeacon.getInstance().addFrameListener( new Delegate( this, __onEnterFrame ) );
}

/**
  *为特定事件添加侦听器。 Add a listener for a specific event.
  * @param t 想要注册的EventType类型。 The type of event we want to register
  * @param o 监听器对象。The object listener
  */
public function addEventListener( t : EventType, o ) : Void
{
  _oEB.addEventListener.apply( _oEB, arguments );
}

/**
  * 移除指定事件的监听器。Remove a listener for a specific event.
  * @param e 想要移除的事件类型。EventType The type of event we want to register
  * @param oL 监听器对象。The object listener
  */
public function removeEventListener( e : EventType, oL ) : Void
{
  _oEB.removeEventListener( e, oL );
}

/**
  * 得到一个World3D的实例。Get the Singleton instance of World3D.
  *
  * @return World3D, the only one instance possible返回World3D,唯一的一个实例。
  */
public static function getInstance () : World3D
{
  if (_inst === undefined) _inst = new World3D();
  return _inst;
}

/**
  * 设置场景的摄影机。Set the {@code Camera3D} of the world.
  *
  * @param cam The new {@link Camera3D}
  */
public function addCamera ( cam:Camera3D ):Number
{
  return _aCams.push( cam ) - 1;
}

/**
  * 获取场景的摄影机列表。Get the list of {@code Camera3D} of the world.
  *
  * @return  The {@link Camera3D} array返回一个数组。
  */
public function getCameraList ( Void ):Array/*Camera3D*/
{
  return _aCams;
}

/**
  * Get the a {@code Camera3D} of the world.获取场景中的一个摄影机。
  * @param id 标识你想要的摄影机,默认为0。Number The id of the camera you want. default is 0.
  * @return  返回Camera3D.The {@link Camera3D}
  */
public function getCamera ( id:Number ):Camera3D
{
  if( !id || id < 0 || id >= _aCams.length ) id = 0;
  return _aCams[ id ];
}

/**
  * 设置3d场景中唯一的灯。We set the unique ligth of the 3D world.
  * @param l 灯光实例。Light3D  The light instance
  * @return Void 无返回直。nothing
  */
public function setLight ( light3D ):Void
{
  _oEB.broadcastEvent( new BasicEvent( World3D.onLightUpdatedEVENT ) );
  _light = l;
}

/**
  * 返回场景中的灯的引用。Returns the world light reference.
  * @param Void Nothing
  * @return Light3D The light reference
  */
public function getLight ( Void )ight3D
{
  return _light;
}

/**
* 为场景添加一个Group.Add a {@code Group} to the world.
*
* @param objGroup 要添加的组。不可以是transformGroup.The group to add. It must not be a transformGroup !
* @return Number  The identifier of the object in the list. With that you will be able to use getGroup method.
*/
public function setRootGroup( objGroup:Group ) :Void
{
  // check if this node have a parent?!!
  _oRoot = objGroup;
}

/**
* 获取场景的根组。 Get the root {@code Group} of the world.
*
* @return Group THe root group of the World3D instance.
*/
public function getRootGroup( Void ):Group
{
  return _oRoot;
}

/**
* 计算所有的组,并绘制他们。Compute all groups, and draw them.
* 应该调用一次Should be call only once, or everytime after a Wordl3D.stop call.
*/
public function render ( Void ) : Void
{
  if( _isRunning == false )
  {
   _isRunning = true;
   // 播报开始消息。we broadcast the start message
   _oEB.broadcastEvent( _eStart );
   //开始实时渲染。 we start the real time rendering
   FPSBeacon.getInstance().start();
  }
}
/**
  * 停止渲染。Stop the rendering of the World3D.
  * 你可以再次渲染通过调用render方法。You can start again th rendering by calling render method.
  */
public function stop( Void ):Void
{
  FPSBeacon.getInstance().stop();
  _isRunning = false;
}

/**
  * 每次都调用的方法。Method called every time.
  */
private function __onEnterFrame( Void ):Void
{
  // 广播事件。we broadcast the event
  _oEB.broadcastEvent( _eRender );
  //-- we make the active BranchGroup render
  __render();
}

/**
* Allows to get the current matrix projection ( usefull since there's several cameras allowed )
* @param Void
* @return Matrix4 The current projection matrix
*/
public function getCurrentProjectionMatrix( Void ):Matrix4
{
  return _mProj;
}
/**
* 可以得到当前摄影机。 Allows to get the current camera
* @param Void
* @return Camera3D The current camera
*/
public function getCurrentCamera( Void ):Camera3D
{
  return _oCam;
}
////////////////////
//// PRIVATE私有
////////////////////
/**
  * Call the recurssive rendering of all the children of this branchGroup.
  * This is the most important method in all the engine, because the mojority of the computations are done here.
  * This method is making the points transformations and 2D projections.
  */
private function __render( Void ) : Void
{
  var l:Number,lc:Number, lp:Number, vx:Number, vy:Number, vz:Number, offx:Number, offy:Number, nbObjects:Number, nbCams:Number;
  var mp11:Number,mp21:Number,mp31:Number,mp41:Number,mp12:Number,mp22:Number,mp32:Number,mp42:Number,mp13:Number,mp23:Number,mp33:Number,mp43:Number,mp14:Number,mp24:Number,mp34:Number,mp44:Number;
  var mp:Matrix4, aV:Array;
  var cam:Camera3D ;
  var obj:Object3D;
  var v:Vertex;
  var crt:Node, crtId:Number;
  // we set a variable to remember the number of objects and in the same time we strop if no objects are displayable
  if( !( nbCams =  _aCams.length ) || _oRoot == null )
   return;
   //-- we initialize
  _bGlbCache = false;
  _aObjects = [];
  _aMatrix  = [];
  _aCache  = [];
  MatrixBuffer.init();
  //
  __parseTree( _oRoot, _oRoot.isModified() );
  // now we check if there are some modifications on that branch
  // if true something has changed and we need to compute again
  l = nbObjects = _aObjects.length;
  while( --l > -1 )
  {
   obj = _aObjects[ l ];
   if( _aCache[ l ] == true )
   {
    mp = _aMatrix[ l ];
    if( mp )
    {
     aV = obj.aPoints;
     //aV.push( obj.getBounds().min, obj.getBounds().max );
     mp11 = mp.n11; mp21 = mp.n21; mp31 = mp.n31;
     mp12 = mp.n12; mp22 = mp.n22; mp32 = mp.n32;
     mp13 = mp.n13; mp23 = mp.n23; mp33 = mp.n33;
     mp14 = mp.n14; mp24 = mp.n24; mp34 = mp.n34;
     // Now we can transform the objet vertices
     lp = aV.length;
     while( --lp > -1 )
     {
      v = aV[lp];
      // computations for projection
      v.tx = (vx = v.x) * mp11 + (vy = v.y) * mp12 + (vz = v.z) * mp13 + mp14;
      v.ty =  vx * mp21 + vy * mp22 + vz * mp23 + mp24;
      v.tz =  vx * mp31 + vy * mp32 + vz * mp33 + mp34;
     }   
    }
    else
    {
     // In this canse we just do a copy of the local position to the transformed
     aV = obj.aPoints;
     lp = aV.length;
     while( --lp > -1 )
     {
      v = aV[lp];
      // computations for projection
      v.tx = v.x;
      v.ty =  v.y;
      v.tz =  v.z;
     }
    }
   }
   else
   {
    ;/* Object cached */
   }
  }

  // -- Now we check if nothing moved on the world and the camera's neither
  lc = nbCams;
  //
  while( --lc > -1 )
  {
   _oCam = cam = _aCams[ lc ];
   // Now we check if nothing moved on the world and the camera's neither
   if( _bGlbCache  || cam.isModified() )
   {
    cam.compile();
    offx = cam.getXOffset(); offy = cam.getYOffset();
    // Camera projection
    _mProj = mp = cam.m ;
    //
    mp11 = mp.n11; mp21 = mp.n21; mp31 = mp.n31; mp41 = mp.n41;
    mp12 = mp.n12; mp22 = mp.n22; mp32 = mp.n32; mp42 = mp.n42;
    mp13 = mp.n13; mp23 = mp.n23; mp33 = mp.n33; mp43 = mp.n43;
    mp14 = mp.n14; mp24 = mp.n24; mp34 = mp.n34; mp44 = mp.n44;
    // Object transformations.
    l = nbObjects;
    while( --l > -1 )
    {
     obj = Object3D( _aObjects[l] );
     aV = obj.aPoints;
     //aV.push( obj.getBounds().min, obj.getBounds().max );
     lp =  aV.length;
     while( --lp > -1 )
     {
      v = aV[lp];
      var c:Number =  1 / ( (vx = v.tx) * mp41 + (vy = v.ty) * mp42 + (vz = v.tz) * mp43 + mp44 );
      // computations for projection
      v.sx = (v.wx = vx * mp11 + vy * mp12 + vz * mp13 + mp14) * c + offx;
      v.sy = (v.wy =  vx * mp21 + vy * mp22 + vz * mp23 + mp24) * c + offy;
      v.wz =  vx * mp31 + vy * mp32 + vz * mp33 + mp34;
     }
     // -- object rendering.
     obj.render();  
    }// end objects loop
    // we sort visibles Faces
    var aF:Array = ZBuffer.sort();
    var s:IScreen = cam.is;
    // -- we draw all sorted Faces
    s.render( aF );
    // -- we clear the ZBuffer
    ZBuffer.dispose ();
   }
   else
   {
    /* Nothing has moved, so nothing to do exept if an object has a texture which has been updated! Let's see */
    l = nbObjects;
    while( --l > -1 )
    {
     obj = Object3D( _aObjects[l] );
     if( obj.needRefresh() )
     {
      obj.refresh();
     }
    }
    // That's all
   }
  } // end cameras
} // end method


private function __parseTree( n:INode, cache:Boolean ):Void
{
  var a:Array = n.getChildList();
  var lCache:Boolean = n.isModified();
  _bGlbCache = _bGlbCache || lCache;
  var l:Number = a.length;

  if( !l )
  {
   _aObjects.push( n );
   _aCache.push( cache || lCache );
   _aMatrix.push( MatrixBuffer.getCurrentMatrix() );
  }
  else
  {
   n.render();
   while( --l > -1 )
   {
    __parseTree( a[l], cache || lCache );
   }
   n.dispose();
  }
  n.setModified( false );
  return;
}


private var _mProj:Matrix4;
private var _oCam:Camera3D;
private var _oRoot:Group;
/**
  * _aGroups : The Array of {@link Group}
  */
private var _aGroups:Array;

/**
  * _cam : The {@link Camera3D} of the World3D
  */  
private var _aCams:Array/*Camera3D*/;
/**
  * _inst : The only one World3D permit
  */  
private static var _inst:World3D;

/**
  * _oEB : The EventBroadcaster instance which manage the event system of world3D.
  */
private var _oEB:EventBroadcaster;
/**
  * the unique light instance of the world
  */
private var _light : Light3D;

private var _eRender:BasicEvent;
private var _eStart:BasicEvent;
private var _isRunning:Boolean;

private var _bGlbCache:Boolean;
private var _aObjects:Array;
private var _aMatrix:Array;
private var _aCache:Array;
}

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-14 12:48 , Processed in 0.106959 second(s), 30 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部