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即可。