Three.js源碼閱讀筆記-5


Core::Ray

該類用來表示空間中的“射線”,主要用來進行碰撞檢測。

THREE.Ray = function ( origin, direction ) {
    this.origin = ( origin !== undefined ) ? origin : new THREE.Vector3();
    this.direction = ( direction !== undefined ) ? direction : new THREE.Vector3();
};

Ray類的構造函數頗為簡單,只有兩個參數origin和direction,顧名思義,也就是端點和方向。

Ray類的主要作用是進行碰撞檢測。

THREE.Ray.prototype = {

    constructor: THREE.Ray,
    set: function ( origin, direction ) {...},
    copy: function ( ray ) {...},

    at: function( t, optionalTarget ) {
        var result = optionalTarget || new THREE.Vector3();
        return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );
    },

    recast: function ( t ) {
        this.origin.copy( this.at( t, THREE.Ray.__v1 ) );
        return this;
    },

    closestPointToPoint: function ( point, optionalTarget ) {
        var result = optionalTarget || new THREE.Vector3();
        result.subVectors( point, this.origin );
        var directionDistance = result.dot( this.direction );
        return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
    },

    distanceToPoint: function ( point ) {
        var directionDistance = THREE.Ray.__v1.subVectors( point, this.origin ).dot( this.direction );
        THREE.Ray.__v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
        return THREE.Ray.__v1.distanceTo( point );
    },

    isIntersectionSphere: function( sphere ) {
        return ( this.distanceToPoint( sphere.center ) <= sphere.radius );
    },

    isIntersectionPlane: function ( plane ) {
        // check if the line and plane are non-perpendicular, if they
        // eventually they will intersect.
        var denominator = plane.normal.dot( this.direction );
        if ( denominator != 0 ) {
            return true;
        }
        // line is coplanar, return origin
        if( plane.distanceToPoint( this.origin ) == 0 ) {
            return true;
        }
        return false;
    },

    distanceToPlane: function ( plane ) {
        var denominator = plane.normal.dot( this.direction );
        if ( denominator == 0 ) {
            // line is coplanar, return origin
            if( plane.distanceToPoint( this.origin ) == 0 ) {
                return 0;
            }
            // Unsure if this is the correct method to handle this case.
            return undefined;
        }
        var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
        return t;
    },

    intersectPlane: function ( plane, optionalTarget ) {
        var t = this.distanceToPlane( plane );
        if( t === undefined ) {
            return undefined;
        }
        return this.at( t, optionalTarget );
    },

    transform: function ( matrix4 ) {...},
    equals: function ( ray ) {...},
    clone: function () {...}
};

 Ray類有這樣一些方法:

  • at(t, optionalTarget):返回射線上與射線端點距離為t的點。如果傳入了optionalTarget參數,那么就將該對象設置為返回的點(下同)。
  • closestPointToPoint: function ( point, optionalTarget ):傳入一個點,返回由該點向射線引垂線得到的垂足。
  • distanceToPoint: function ( point ):傳入一個點,返回該點到射線的距離。
  • distanceToPlane: function( plane ):傳入一個平面,返回該平面到與射線的距離(如果射線與平面不平行,那么距離就為0)。
  • isIntersectionSphere:function( sphere ):判斷射線是否與一個球體有交點,傳入的參數sphere需要有radius和center屬性(比如,傳入sphereGeometry就是沒用的)。
  • isIntersectionPlane:function( plane ):判斷射線是否與一個平面有交點,傳入的參數plane需要有normal屬性。
  • recast(t):將Three.Ray.__v1(這個變量)設置為調用者的at(t)位置。(Three.Ray.__v1和Three.Ray.__v2是定義在Three.Ray而不是其peototype上的臨時變量,類似於C++中的靜態變量)。

Material::MeshBasicMaterial

之前我們分析過Material類和LineBasicMaterial類,現在我們來看剩下的幾個材質類。MeshBasicMaterial是一種“光照無關”的材質,也就是說,在沒有光照的情況下,材質依然能夠要顯示出來。

THREE.MeshBasicMaterial = function ( parameters ) {

    THREE.Material.call( this );
    this.color = new THREE.Color( 0xffffff ); // emissive

    this.map = null;
    this.lightMap = null;
    this.specularMap = null;
    this.envMap = null;

    this.combine = THREE.MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;

    this.fog = true;
    this.shading = THREE.SmoothShading;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.vertexColors = THREE.NoColors;

    this.skinning = false;
    this.morphTargets = false;
    this.setValues( parameters );
};

MeshBasicMaterial包括這樣一些屬性:

  • color:顏色,十六進制整數,如果設定了color屬性,整個材質將全部使用這種顏色。
  • map:映射,可以指向Three.Texture的實例對象。實際上,紋理就是一種映射,從一個[0,1][0,1]范圍的二維坐標到顏色值的映射,過程就是從紋理圖片的響應位置上取顏色。當然也有不依賴於圖片的紋理,比如一些簡單的三角函數的組合,將而為坐標轉化為顏色,也能夠成為紋理。這種紋理可以在表面上繪制復雜的圖案。
  • lightMap,envMap,specularMap:字面的意思是光照映射,光譜映射等,可能用來服務於Three中的某些類型的着色器。
  • wireframe:如果設定為true,那么整個幾何形狀就顯示為網格狀的(即只顯示邊,不顯示面)。
  • wireframeLinecap,wireframeLinewidth,wireframeLinejoin:采用wireframe模式時,控制網格的線段端點,線段寬度,線段交點等。
  • fog:顯示材質的顏色是否會被全局的fog設定影響。
  • vertexColors:數組,每個元素都是一個Three.Color變量。如果設定了這個變量,那么這個數組的前3個或4個元素(視面的類型),就是面的端點的顏色。而在默認的片元着色器中,面上的顏色是由端點顏色內插而來的。
  • morphTarget:如果設置為true,那么就可以使用morphTarget模式(一種利用着色器來計算頂點位置的方法,可以高效地產生類似於windows98形變屏保模式的方法,在我的前面一片demo源碼閱讀筆記中有詳細敘述)。
  • MeshBasicMaterial本身只有一個clone方法(該方法調用Material的clone方法),其他方法都是繼承自Material方法。

Material::MeshLambertMaterial

MeshLambertMaterial是一種朗伯面材質。朗伯面就是各向反射同性面,任何角度的光線照射上去,反射的亮度和反射角度無關。以下摘錄了除掉與MeshBasicMaterial重復的屬性剩下的若干個屬性。

THREE.MeshLambertMaterial = function ( parameters ) {
    THREE.Material.call( this );
    this.color = new THREE.Color( 0xffffff ); // diffuse
    this.ambient = new THREE.Color( 0xffffff );
    this.emissive = new THREE.Color( 0x000000 );

    this.wrapAround = false;
    this.wrapRGB = new THREE.Vector3( 1, 1, 1 );

    this.combine = THREE.MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    ...

    this.setValues( parameters );
};

 除了MeshBasicMaterial中的color,vertexColors等屬性,MeshLambertMaterial類還具有幾個跟光照相關的屬性:

  • color:主顏色,當然如果設置了采用映射或者為每個端點賦值顏色,就沒有用了。
  • ambient:環境色,默認為白色,如果改變的話,會整體影響材質看上去的的顏色。
  • emissive:發射光的顏色,默認為黑色,即其中與MeshBasicMaterial原理類似的部分。默認情況下,如果沒有光照,而且render的clearColor設置為黑色(考慮光照,這是通常的情況)的話,一個使用MeshLambertMaterial的物體時看不到的,但是如果這里改成其他顏色,應當就能看到。
  • combine:光照與顏色混合的方式,默認為乘法。
  • reflectivity:反射率,默認為1,即全部反射。
  • refractionRatio:折射率(即穿透物體一個單位長度后衰減的比率),可能用於透明物體。 

Material::MeshPhongMaterial 

MeshPhongMaterial,旁氏反射面,表示有光澤的物體,在極端情況下就是鏡面。

THREE.MeshPhongMaterial = function ( parameters ) {

    THREE.Material.call( this );

    this.color = new THREE.Color( 0xffffff ); // diffuse
    this.ambient = new THREE.Color( 0xffffff );
    this.emissive = new THREE.Color( 0x000000 );
    this.specular = new THREE.Color( 0x111111 );
    this.shininess = 30;

    this.metal = false;
    this.perPixel = true;

this.bumpMap = null; this.bumpScale = 1; this.normalMap = null; this.normalScale = new THREE.Vector2( 1, 1 ); ...this.setValues( parameters ); };

 暫時還沒大弄明白。

Material::MeshFaceMaterial

允許為某個geometry的每個面單獨指定材質,通常用於從三維模型中讀取數據,然后構造mesh。

THREE.MeshFaceMaterial = function ( materials ) {

    this.materials = materials instanceof Array ? materials : [];

};

 只需要傳入一個數組作為參數,其materials數組的每一個元素都是某種MeshXXXXMaterial,然后再geometry中創建表面時,為face指定materialIndex即可。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM