Commit 5083036a authored by wjf's avatar wjf

l

parent eb48868f
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/fyge_for_tb.iml" filepath="$PROJECT_DIR$/.idea/fyge_for_tb.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="ca828aa9-7d32-43b5-949b-5692dab70d5f" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/build/fyge.min.js" beforeDir="false" afterPath="$PROJECT_DIR$/build/fyge.min.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/debug/FYGE.js.map" beforeDir="false" afterPath="$PROJECT_DIR$/debug/FYGE.js.map" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/2d/display/DisplayObject.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/2d/display/DisplayObject.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.ts" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
<entry key="$PROJECT_DIR$" value="master" />
</map>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectId" id="1cnYJkANRv6RhvOeL2ofjHPqQTl" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/scripts" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="settings.editor.selected.configurable" value="editor.preferences.fonts.default" />
<property name="ts.external.directory.path" value="$PROJECT_DIR$/node_modules/typescript/lib" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/scripts" />
<recent name="$PROJECT_DIR$" />
</key>
</component>
<component name="RunManager" selected="npm.dev1">
<configuration name="build" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="build" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
<configuration name="dev" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
<configuration name="dev1" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev1" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
<configuration name="watch" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="watch" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="npm.dev1" />
<item itemvalue="npm.build" />
<item itemvalue="npm.dev" />
<item itemvalue="npm.watch" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="ca828aa9-7d32-43b5-949b-5692dab70d5f" name="Default Changelist" comment="" />
<created>1591165754614</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1591165754614</updated>
<workItem from="1591165756008" duration="509000" />
<workItem from="1591166636799" duration="1935000" />
<workItem from="1591239594676" duration="141000" />
<workItem from="1591239837585" duration="1375000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="2" />
<option name="exactExcludedFiles">
<list>
<option value="$PROJECT_DIR$/src/2d/renderers/plugins/BatchRenderer.js" />
</list>
</option>
</component>
<component name="WindowStateProjectService">
<state width="1878" height="330" key="GridCell.Tab.0.bottom" timestamp="1591241021547">
<screen x="1680" y="-199" width="1920" height="1177" />
</state>
<state width="1878" height="330" key="GridCell.Tab.0.bottom/37.23.1643.1027/1680.-199.1920.1177@1680.-199.1920.1177" timestamp="1591241021547" />
<state width="1878" height="330" key="GridCell.Tab.0.center" timestamp="1591241021545">
<screen x="1680" y="-199" width="1920" height="1177" />
</state>
<state width="1878" height="330" key="GridCell.Tab.0.center/37.23.1643.1027/1680.-199.1920.1177@1680.-199.1920.1177" timestamp="1591241021545" />
<state width="1878" height="330" key="GridCell.Tab.0.left" timestamp="1591241021545">
<screen x="1680" y="-199" width="1920" height="1177" />
</state>
<state width="1878" height="330" key="GridCell.Tab.0.left/37.23.1643.1027/1680.-199.1920.1177@1680.-199.1920.1177" timestamp="1591241021545" />
<state width="1878" height="330" key="GridCell.Tab.0.right" timestamp="1591241021546">
<screen x="1680" y="-199" width="1920" height="1177" />
</state>
<state width="1878" height="330" key="GridCell.Tab.0.right/37.23.1643.1027/1680.-199.1920.1177@1680.-199.1920.1177" timestamp="1591241021546" />
<state x="2305" y="66" width="670" height="676" key="search.everywhere.popup" timestamp="1591241201422">
<screen x="1680" y="-199" width="1920" height="1177" />
</state>
<state x="2305" y="66" width="670" height="676" key="search.everywhere.popup/37.23.1643.1027/1680.-199.1920.1177@1680.-199.1920.1177" timestamp="1591241201422" />
</component>
</project>
\ No newline at end of file
......@@ -11,4 +11,3 @@ webpack.config.js
/dist
rollup.config.js
record.txt
\ No newline at end of file
test
\ No newline at end of file
This diff is collapsed.
File added
This diff is collapsed.
This diff is collapsed.
{
"name": "fyge-tbmini",
"version": "1.3.5",
"description": "淘宝小程序canvas渲染引擎",
"description": "canvas渲染引擎",
"main": "./build/fyge.min.js",
"types": "./build/FYGE.d.ts",
"dependencies": {},
......@@ -31,6 +31,6 @@
"typescript": "^2.7.2"
},
"keywords": [
"淘宝小程序,canvas,webgl"
"h5,淘宝小程序,canvas,webgl,2d,3d"
]
}
......@@ -401,4 +401,12 @@ export function removeItems(arr: Array<any>, startIdx: number, removeCount: numb
arr.length = len
}
/**
* 取符合范围的值
* @param value
* @param min
* @param max
*/
export function clamp(value: number, min: number, max: number) {
return Math.max(min, Math.min(max, value));
}
\ No newline at end of file
This diff is collapsed.
import { Vector3 } from "./math/Vector3";
import { VertexArrayObject, GLBuffer, GLShader } from "../glCore";
import { HashObject } from "../2d/HashObject";
import { Vector2 } from "./math/Vector2";
import { BatchBuffer } from "../2d/renderers/webgl/BatchBuffer";
import { Box3 } from "./math/Box3";
import { Sphere } from "./math/Sphere";
/**
* 考虑需要记录哪些几何数据
* 暂时都在构造中执行一次数据的赋值,如果以后涉及需要动态修改数据的,加标记修改,插件里也需要重新upload数据
*/
export class Geometry extends HashObject {
/**
* 顶点坐标3,颜色3,uv2,法线3
*/
_vertByteSize: number = (3 + 3 + 2 + 3) * 4;
_vertices: Float32Array | number[];
_indices: Uint16Array | number[];
_colors: Float32Array | number[];
_uvs: Float32Array | number[];
_normals: Float32Array | number[];
boundingBox: Box3 = null;
boundingSphere: Sphere = null;
/**
* 为了不同渲染器上下文对应自己的vao,不管program吧,可能不同着色器程序,带的attr可能不一样,
* 在3d的插件上处理
* 建vao,添加attr属性
* 激活绑定vao
* 绑定buffer,
* 上传buffer数据
* 绘制
*
*/
// _glVertexArrayObjects: { [key: number]: VertexArrayObject }
_glVaoBuffer: { [key: number]: VaoBufferInt }
/**
* 记录顶点数据用
*/
_attrBuffer: BatchBuffer;
/**
* 索引数据
*/
/**
*
* @param vertices
* @param indices
* @param colors
* @param uvs
*/
constructor(
vertices: Float32Array | number[],
indices?: Uint16Array | number[],
normals?: Float32Array | number[],
colors?: Float32Array | number[],
uvs?: Float32Array | number[]
) {
super();
this._instanceType = "Geometry";
this._glVaoBuffer = {};
this._vertices = vertices;
this._normals = normals || new Float32Array(vertices.length);
this._colors = colors || new Float32Array(vertices.length).map(() => { return 1 });//不传就全是白色
this._uvs = uvs || new Float32Array(vertices.length / 3 * 2);
//索引直接用,可能没有
this._indices = indices ? new Uint16Array(indices) : null;
//顶点长度先记录
this._attrBuffer = new BatchBuffer(vertices.length / 3 * this._vertByteSize);
// this.computeBoundingBox();
}
computeBoundingBox() {
if (this.boundingBox === null) this.boundingBox = new Box3();
var position = this._vertices;
if (position !== undefined) {
this.boundingBox.setFromArray(position);
} else {
this.boundingBox.makeEmpty();
}
if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) console.error("顶点数据有误")
};
computeBoundingSphere() {
var box = new Box3();
var vector = new Vector3();
if (this.boundingSphere === null) this.boundingSphere = new Sphere();
var position = this._vertices;
if (position) {
var center = this.boundingSphere.center;
box.setFromArray(position);
box.getCenter(center);
// hoping to find a boundingSphere with a radius smaller than the
// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
var maxRadiusSq = 0;
for (var i = 0, il = position.length; i < il; i += 3) {
vector.x = position[i];
vector.y = position[i + 1];
vector.z = position[i + 2];
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector));
}
this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
if (isNaN(this.boundingSphere.radius)) console.error("顶点数据有误")
}
};
destroy() {
}
}
/**
* 根据webglRendererId存一个,vao还需要根据着色器程序缓存
*/
interface VaoBufferInt {
/**
* 索引
*/
indexBuffer?: GLBuffer,
/**
* 顶点相关属性
*/
attrBuffer: GLBuffer,
/**
* 需要根据着色器程序id作为指向,
* 灯光重置过着色器,基本要重来一次,上面的buffer可以留着,重新addAttr到新的vao
*/
vaos: { [key: string]: VertexArrayObject }
}
var vertices = new Float32Array([
2.0, 2.0, 2.0, -2.0, 2.0, 2.0, -2.0, -2.0, 2.0, 2.0, -2.0, 2.0, // v0-v1-v2-v3 front
2.0, 2.0, 2.0, 2.0, -2.0, 2.0, 2.0, -2.0, -2.0, 2.0, 2.0, -2.0, // v0-v3-v4-v5 right
2.0, 2.0, 2.0, 2.0, 2.0, -2.0, -2.0, 2.0, -2.0, -2.0, 2.0, 2.0, // v0-v5-v6-v1 up
-2.0, 2.0, 2.0, -2.0, 2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, 2.0, // v1-v6-v7-v2 left
-2.0, -2.0, -2.0, 2.0, -2.0, -2.0, 2.0, -2.0, 2.0, -2.0, -2.0, 2.0, // v7-v4-v3-v2 down
2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, 2.0, -2.0, 2.0, 2.0, -2.0 // v4-v7-v6-v5 back
]);
var colors = new Float32Array([ // Colors
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v1-v2-v3 front
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v5-v6-v1 up
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v1-v6-v7-v2 left
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v7-v4-v3-v2 down
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0  // v4-v7-v6-v5 back
]);
colors = colors.map(() => {
return 1
})
var normals = new Float32Array([ // Normal
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0 // v4-v7-v6-v5 back
]);
var uvs = new Float32Array([
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
]);
var indices = new Uint16Array([ // Indices of the vertices
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // right
8, 9, 10, 8, 10, 11, // up
12, 13, 14, 12, 14, 15, // left
16, 17, 18, 16, 18, 19, // down
20, 21, 22, 20, 22, 23 // back
]);
function createNineTextures(imageUrl: string): Promise<FYGE.Texture[]> {
return new Promise((resolve, reject) => {
let image = new Image();
image.onload = function () {
var obj = {}
//名字。
var name = "lalala";
var w = image.width / 3;
var h = image.height / 3;
//生成9张图的数据
for (var i = 0; i < 9; i++)
obj[name + i] = {
"x": i % 3 * w,
"y": ~~(i / 3) * h,
w, h, sw: w, sh: h, ox: 0, oy: 0, ro: false
};
FYGE.createTextureSheet(new FYGE.BaseTexture(image), obj);
//取TextureCache里的
var arr = [];
for (var i = 0; i < 9; i++)arr.push(FYGE.TextureCache[name + i])
resolve(arr)
}
image.onerror = function () {
reject()
}
image.src = imageUrl
})
}
import { Object3D } from "./Object3D";
import { Geometry } from "./Geometry";
import { BaseMaterial, RenderSideType } from "./materials/BaseMaterial";
import { Matrix4 } from "./math/Matrix4";
import { Ray } from "./math/Ray";
import { Sphere } from "./math/Sphere";
import { Vector3 } from "./math/Vector3";
import { Vector2 } from "./math/Vector2";
import { Raycaster, IntersectData } from "./Raycaster";
const templeSphere: Sphere = new Sphere();
const tempMatrix: Matrix4 = new Matrix4();
const tempRay: Ray = new Ray();
const tempPoint = new Vector3();
export class Mesh3D extends Object3D {
constructor(
public geometry: Geometry,
public material: BaseMaterial
) {
super();
}
_render(renderer) {
if (!this.visible) return
renderer.batchManager.setObjectRenderer(renderer.plugins["d3"]);
renderer.plugins["d3"].render(this)
}
raycast(raycaster: Raycaster, intersects: IntersectData[]) {
if (!this.visible || !this.geometry || !this.material || this.material.wireframe) return;
var geometry = this.geometry;
var matrixWorld = this._worldMatrix;
// Checking boundingSphere distance to ray
if (!geometry.boundingSphere) geometry.computeBoundingSphere();
templeSphere.copy(geometry.boundingSphere);
templeSphere.applyMatrix4(matrixWorld);
if (raycaster.ray.intersectsSphere(templeSphere) === false) return;
//
tempMatrix.setInverseOf(matrixWorld);
tempRay.copy(raycaster.ray).applyMatrix4(tempMatrix);
// Check boundingBox before continuing
if (geometry.boundingBox !== null && tempRay.intersectsBox(geometry.boundingBox) === false) return;
var intersection: IntersectData;
var a = new Vector3(), b = new Vector3(), c = new Vector3();
var index = geometry._indices;
var position = geometry._vertices;
if (index) {
for (var i = 0; i < index.length; i += 3) {
a.set(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);
b.set(position[(i + 1) * 3], position[(i + 1) * 3 + 1], position[(i + 1) * 3 + 2]);
c.set(position[(i + 2) * 3], position[(i + 2) * 3 + 1], position[(i + 2) * 3 + 2]);
intersection = checkIntersection(
this,
raycaster,
tempRay,
a,
b,
c,
tempPoint
);
if (intersection) {//有一个就出
intersects.push(intersection);
break;
}
}
}
else if (position) {
for (var i = 0; i < position.length; i += 9) {
a.set(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);
b.set(position[(i + 1) * 3], position[(i + 1) * 3 + 1], position[(i + 1) * 3 + 2]);
c.set(position[(i + 2) * 3], position[(i + 2) * 3 + 1], position[(i + 2) * 3 + 2]);
intersection = checkIntersection(
this,
raycaster,
tempRay,
a,
b,
c,
tempPoint
);
if (intersection) {//有一个就出
intersects.push(intersection);
break;
}
}
}
};
}
var intersectionPointWorld = new Vector3();
function checkIntersection(
object: Mesh3D,
raycaster: Raycaster,
ray: Ray,
pA: Vector3,
pB: Vector3,
pC: Vector3,
point: Vector3
): IntersectData {
var material = object.material
var intersect: Vector3 | null;
if (material.side === RenderSideType.BackSide) {
intersect = ray.intersectTriangle(pC, pB, pA, true, point);
} else {
intersect = ray.intersectTriangle(pA, pB, pC, material.side !== RenderSideType.DoubleSide, point);
}
if (intersect === null) return null;
intersectionPointWorld.copy(point);
intersectionPointWorld.applyMatrix4(object._worldMatrix);
var distance = raycaster.ray.origin.distanceTo(intersectionPointWorld);
if (distance < raycaster.near || distance > raycaster.far) return null;
return {
distance: distance,
point: intersectionPointWorld.clone(),
object: object
};
}
//交付分
var a = 5
//时间分每天
var b = 1
//极限时间
var j = 15
//项目基础时间
var i = 4
function aaa(t) {
t -= i
return a + t * b + (t * t) / j * a / i / i;
}
function bbb(t) {
//完整项目按4天
t -= i
return a + t * b + (t * t) / j * a / i / i;
}
\ No newline at end of file
This diff is collapsed.
import { Ray } from './math/Ray';
import { Vector2 } from './math/Vector2';
import { Vector3 } from "./math/Vector3"
import { Camera } from './cameras/Camera';
import { Object3D } from './Object3D';
import { Mesh3D } from './Mesh3D';
//射线检测工具,暂时不对外导了
export class Raycaster {
public ray: Ray
constructor(
origin: Vector3,
direction: Vector3,
public near: number = 0,
public far: number = Infinity
) {
this.ray = new Ray(origin, direction);
}
set(origin: Vector3, direction: Vector3) {
this.ray.set(origin, direction);
}
setFromCamera(coords: Vector3, camera: Camera) {
// if ( ( camera && camera.isPerspectiveCamera ) ) {
this.ray.origin.setFromMatrixPosition(camera._worldMatrix);
this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize();
// } else if ( ( camera && camera.isOrthographicCamera ) ) {
// this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
// this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
// } else {
// console.error( 'THREE.Raycaster: Unsupported camera type.' );
// }
};
intersectObject(object: Object3D, optionalTarget?: IntersectData[]) {
var intersects = optionalTarget || [];
intersectObject(object, this, intersects);
intersects.sort(ascSort);
return intersects;
}
}
function ascSort(a: IntersectData, b: IntersectData) {
return a.distance - b.distance;
}
function intersectObject(object: Object3D, raycaster: Raycaster, intersects: IntersectData[]) {
if (object.visible === false) return;
if (object.mouseEnable) object.raycast(raycaster, intersects);
if (object.mouseChildren) {
var children = object.children;
for (var i = 0, l = children.length; i < l; i++) {
intersectObject(children[i], raycaster, intersects);
}
}
}
export interface IntersectData {
distance: number,
point: Vector3,
object: Object3D,
uv?: Vector2,//以后再说
// face?:Face3,
}
This diff is collapsed.
import { Object3D } from "../Object3D";
import { Matrix4 } from "../math/Matrix4";
import { Vector3 } from "../math/Vector3";
export class Camera extends Object3D {
worldMatrixInverse: Matrix4;
projectionMatrix: Matrix4;
projectionMatrixInverse: Matrix4;
constructor() {
super();
this._instanceType = 'Camera';
this.worldMatrixInverse = new Matrix4();
this.projectionMatrix = new Matrix4();
this.projectionMatrixInverse = new Matrix4();
}
/**
* 重写
* @param recursive
*/
clone() {
return new Camera().copy(this);
}
copy(source, recursive?) {
super.copy(source, recursive)
// Object3D.prototype.copy.call(this, source, recursive);
this.worldMatrixInverse.copy(source.matrixWorldInverse);
this.projectionMatrix.copy(source.projectionMatrix);
this.projectionMatrixInverse.copy(source.projectionMatrixInverse);
return this;
};
getWorldDirection(target:Vector3) {
this.updateWorldMatrix();
var e = this._worldMatrix.elements;
return target.set(- e[8], - e[9], - e[10]).normalize();
}
updateWorldMatrix() {
super.updateWorldMatrix()
this.worldMatrixInverse.setInverseOf(this._worldMatrix);
}
}
\ No newline at end of file
import { Camera } from "./Camera";
/**
*
*/
export class PerspectiveCamera extends Camera {
zoom: number;
focus: number;
/**
*
* @param fov 张角
* @param aspect 长宽比例width/height
* @param near 最近近距离
* @param far 最远远距离
*/
constructor(
public fov: number = 50,
public aspect: number = 1,
public near: number = 0.1,
public far: number = 2000
) {
super();
this._instanceType = 'PerspectiveCamera';
this.zoom = 1;
this.focus = 10;
this.updateProjectionMatrix();
}
set(
fov: number = 50,
aspect: number = 1,
near: number = 0.1,
far: number = 2000
) {
this.fov = fov;
this.aspect = aspect;
this.near = near;
this.far = far;
this.zoom = 1;
this.focus = 10;
this.updateProjectionMatrix();
}
copy(source: PerspectiveCamera, recursive: boolean = true) {
super.copy(source, recursive)
this.fov = source.fov;
this.zoom = source.zoom;
this.near = source.near;
this.far = source.far;
this.focus = source.focus;
this.aspect = source.aspect;
return this;
}
/**
* 更新
*/
updateProjectionMatrix() {
this.projectionMatrix.setPerspective(this.fov, this.aspect, this.near, this.far);
this.projectionMatrixInverse.setInverseOf(this.projectionMatrix);
}
}
\ No newline at end of file
import { Geometry } from "../Geometry";
import { Vector3 } from "../math/Vector3";
/**
* 顶点创建方式直接用three的
*/
export class BoxGeometry extends Geometry {
constructor(
width: number = 1,
height: number = 1,
depth: number = 1,
widthSegments: number = 1,
heightSegments: number = 1,
depthSegments: number = 1,
) {
// segments
widthSegments = Math.floor(widthSegments) || 1;
heightSegments = Math.floor(heightSegments) || 1;
depthSegments = Math.floor(depthSegments) || 1;
// buffers
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
// helper variables
var numberOfVertices = 0;
var groupStart = 0;
// build each side of the box geometry
buildPlane('z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0); // px
buildPlane('z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1); // nx
buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2); // py
buildPlane('x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3); // ny
buildPlane('x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4); // pz
buildPlane('x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5); // nz
function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) {
var segmentWidth = width / gridX;
var segmentHeight = height / gridY;
var widthHalf = width / 2;
var heightHalf = height / 2;
var depthHalf = depth / 2;
var gridX1 = gridX + 1;
var gridY1 = gridY + 1;
var vertexCounter = 0;
var groupCount = 0;
var ix, iy;
var vector = new Vector3();
// generate vertices, normals and uvs
for (iy = 0; iy < gridY1; iy++) {
var y = iy * segmentHeight - heightHalf;
for (ix = 0; ix < gridX1; ix++) {
var x = ix * segmentWidth - widthHalf;
// set values to correct vector component
vector[u] = x * udir;
vector[v] = y * vdir;
vector[w] = depthHalf;
// now apply vector to vertex buffer
vertices.push(vector.x, vector.y, vector.z);
// set values to correct vector component
vector[u] = 0;
vector[v] = 0;
vector[w] = depth > 0 ? 1 : - 1;
// now apply vector to normal buffer
normals.push(vector.x, vector.y, vector.z);
// uvs
uvs.push(ix / gridX);
// uvs.push(1 - (iy / gridY));
uvs.push(iy / gridY);//2D里面颠倒过贴图
// counters
vertexCounter += 1;
}
}
// indices
// 1. you need three indices to draw a single face
// 2. a single segment consists of two faces
// 3. so we need to generate six (2*3) indices per segment
for (iy = 0; iy < gridY; iy++) {
for (ix = 0; ix < gridX; ix++) {
var a = numberOfVertices + ix + gridX1 * iy;
var b = numberOfVertices + ix + gridX1 * (iy + 1);
var c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
var d = numberOfVertices + (ix + 1) + gridX1 * iy;
// faces
indices.push(a, b, d);
indices.push(b, c, d);
// increase counter
groupCount += 6;
}
}
// add a group to the geometry. this will ensure multi material support
//每个面当作独立的组,为了能各自改变,暂时不管
// scope.addGroup(groupStart, groupCount, materialIndex);
// calculate new start value for groups
groupStart += groupCount;
// update total number of vertices
numberOfVertices += vertexCounter;
}
//传入数据
super(vertices, indices, normals, null, uvs)
}
}
\ No newline at end of file
import { Geometry } from "../Geometry";
export class PlaneGeometry extends Geometry {
constructor(
width: number = 1,
height: number = 1,
widthSegments: number = 1,
heightSegments: number = 1
) {
var width_half = width / 2;
var height_half = height / 2;
var gridX = Math.floor(widthSegments);
var gridY = Math.floor(heightSegments);
var gridX1 = gridX + 1;
var gridY1 = gridY + 1;
var segment_width = width / gridX;
var segment_height = height / gridY;
var ix, iy;
// buffers
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
// generate vertices, normals and uvs
for (iy = 0; iy < gridY1; iy++) {
var y = iy * segment_height - height_half;
for (ix = 0; ix < gridX1; ix++) {
var x = ix * segment_width - width_half;
vertices.push(x, - y, 0);
normals.push(0, 0, 1);
uvs.push(ix / gridX);
// uvs.push(1 - (iy / gridY));
uvs.push(iy / gridY);
}
}
// indices
for (iy = 0; iy < gridY; iy++) {
for (ix = 0; ix < gridX; ix++) {
var a = ix + gridX1 * iy;
var b = ix + gridX1 * (iy + 1);
var c = (ix + 1) + gridX1 * (iy + 1);
var d = (ix + 1) + gridX1 * iy;
// faces
indices.push(a, b, d);
indices.push(b, c, d);
}
}
super(vertices, indices, normals, null, uvs)
}
}
\ No newline at end of file
import { Geometry } from "../Geometry";
import { Vector3 } from "..";
/**
* 球形几何
* 直接参考three的计算方式
*/
export class SphereGeometry extends Geometry {
constructor(
radius: number = 1,
widthSegments: number = 8,
heightSegments: number = 6,
phiStart: number = 0,
phiLength: number = Math.PI * 2,
thetaStart: number = 0,
thetaLength: number = Math.PI,
) {
//处理分段,必须正整数
widthSegments = Math.max(3, Math.floor(widthSegments));
heightSegments = Math.max(2, Math.floor(heightSegments));
//计算所有顶点,及索引及法线
var thetaEnd = thetaStart + thetaLength;
var ix: number, iy: number;
var index = 0;
var grid = [];
var vertex = new Vector3();
var normal = new Vector3();
// buffers
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
// generate vertices, normals and uvs
for (iy = 0; iy <= heightSegments; iy++) {
var verticesRow = [];
var v = iy / heightSegments;
for (ix = 0; ix <= widthSegments; ix++) {
var u = ix / widthSegments;
// vertex
vertex.x = - radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
vertices.push(vertex.x, vertex.y, vertex.z);
// normal
normal.set(vertex.x, vertex.y, vertex.z).normalize();
normals.push(normal.x, normal.y, normal.z);
// uv
// uvs.push(u, 1 - v);
uvs.push(u, v);//2d里面颠倒过贴图的y轴(其实是矫正)。所以v统统不用1-
verticesRow.push(index++);
}
grid.push(verticesRow);
}
// indices
for (iy = 0; iy < heightSegments; iy++) {
for (ix = 0; ix < widthSegments; ix++) {
var a = grid[iy][ix + 1];
var b = grid[iy][ix];
var c = grid[iy + 1][ix];
var d = grid[iy + 1][ix + 1];
if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
}
}
super(vertices, indices, normals, null, uvs)
}
}
\ No newline at end of file
export * from "./SphereGeometry"
export * from "./BoxGeometry"
export * from "./PlaneGeometry"
\ No newline at end of file
import { Mesh3D } from "../Mesh3D";
import { Geometry } from "../Geometry";
import { BaseMaterial } from "../materials";
export class AxesHelper extends Mesh3D {
constructor(size: number = 1) {
var vertices = [
0, 0, 0, size, 0, 0,
0, 0, 0, 0, size, 0,
0, 0, 0, 0, 0, size
];
var colors = [
1, 0, 0, 1, 0.6, 0,
0, 1, 0, 0.6, 1, 0,
0, 0, 1, 0, 0.6, 1
];
var geometry = new Geometry(vertices, null, null, colors)
var material = new BaseMaterial({ wireframe: true })
super(geometry,material)
}
}
import { Geometry } from "../Geometry";
import { Mesh3D } from "../Mesh3D";
import { BaseMaterial } from "../materials";
import { hex2rgb } from "../../2d/utils";
export class GridHelper extends Mesh3D {
constructor(
size: number = 10,
divisions: number = 10,
color1: number = 0x444444,
color2: number = 0x888888
) {
var center = divisions / 2;
var step = size / divisions;
var halfSize = size / 2;
var colorArr1 = hex2rgb(color1);
var colorArr2 = hex2rgb(color2);
var vertices = [], colors = [];
for (var i = 0, j = 0, k = - halfSize; i <= divisions; i++, k += step) {
vertices.push(- halfSize, 0, k, halfSize, 0, k);
vertices.push(k, 0, - halfSize, k, 0, halfSize);
var color = i === center ? colorArr1 : colorArr2;
let count = 4;
while (count--) {
colors.push(color[0], color[1], color[2])
}
}
var geometry = new Geometry(vertices, null, null, colors)
var material = new BaseMaterial({ wireframe: true });
super(geometry, material)
}
}
export * from "./AxesHelper"
export * from "./GridHelper"
\ No newline at end of file
export * from "./Mesh3D"
export * from "./Geometry"
export * from "./Scene3D"
// export * from "./Math"
export * from "./math/Euler";
export * from "./math/Matrix4";
export * from "./math/Quaternion";
export * from "./math/Vector2";
export * from "./math/Vector3";
//几何
export * from "./geometries"
//材质
export * from "./materials";
//灯光
export * from "./lights";
//辅助类
export * from "./helpers";
//相机
export * from "./cameras/PerspectiveCamera";
//渲染插件
export * from "./D3Renderer"
import { Vector3 } from '../math/Vector3';
import { Light } from './Light';
export class AmbientLight extends Light {
constructor(color: number, intensity: number) {
super(color, intensity);
this._instanceType = "AmbientLight"
}
}
import { Object3D } from '../Object3D';
import { Light } from './Light';
import { Vector3 } from '../math/Vector3';
export class DirectionalLight extends Light {
/**
* 目标对象
*/
target: Object3D;
constructor(color: number, intensity: number) {
super(color, intensity)
this._instanceType = "DirectionalLight";
//位置默认一个
this.position.copy(Object3D.DefaultUp);
// this.updateMatrix();
this.updateLocalMatrix();
//目标默认一个,算方向用
this.target = new Object3D();
}
copy(directionalLight: DirectionalLight) {
super.copy(directionalLight);
this.target = directionalLight.target.clone();
return this
}
}
import { Object3D } from "../Object3D";
import { Vector3 } from "../math/Vector3";
import { rgb2hex, hex2rgb } from "../../2d/utils";
/**
* 光源基类,只有颜色和光源强度
*/
export class Light extends Object3D {
private _color: number = 0xffffff;
private _colorArr: Float32Array = new Float32Array([1.0, 1.0, 1.0]);
private _colorVec3: Vector3 = new Vector3(1.0, 1.0, 1.0);
get color() {
return this._color;
}
set color(value: number) {
if (this._color === value) return;
this._color = value;
var arr = hex2rgb(value)
this._colorArr[0] = this._colorVec3.x = arr[0];
this._colorArr[1] = this._colorVec3.y = arr[1];
this._colorArr[2] = this._colorVec3.z = arr[2];
}
//获取
get colorArr() {
return this._colorArr;
}
get colorVec3() {
return this._colorVec3;
}
/**
*
* @param color rgb三分量的矢量,每个分量0到1,颜色方面后续优化
* @param intensity 光照强度 0到1 ,直接影响颜色值,不进uniform
*/
constructor(
color: number,
public intensity: number = 1
) {
super();
this.color = color;
this._instanceType = "Light"
}
copy(light: Light) {
super.copy(light);
this.color = light.color;
this.intensity = light.intensity;
return this
}
}
\ No newline at end of file
import { Light } from "./Light";
import { Vector3 } from "../math/Vector3";
export class PointLight extends Light {
/**
*
* @param color 颜色值,0到1的矢量
* @param intensity 强度
* @param distance 最大影响距离
* @param decay 衰减系数,//多试试2
*/
constructor(
color: number,
intensity: number,
public distance: number = 0,
public decay: number = 1
) {
super(color, intensity);
this._instanceType = "PointLight";
}
get power(): number {
return this.intensity * 4 * Math.PI;
}
set power(value: number) {
this.intensity = value / (4 * Math.PI);
}
copy(pointLight: PointLight) {
super.copy(pointLight);
this.distance = pointLight.distance;
this.decay = pointLight.decay;
return this
}
}
\ No newline at end of file
export * from "./AmbientLight"
export * from "./DirectionalLight"
export * from "./PointLight"
\ No newline at end of file
import { HashObject } from "../../2d/HashObject";
import { Texture } from "../../2d/texture";
import { Vector3 } from "../math/Vector3";
import { hex2rgb } from "../../2d/utils";
export enum RenderSideType {
/**
* 正面才渲染,逆时针顶点
*/
FrontSide = 0,
/**
* 反面才渲染,顺时针顶点顺序
*/
BackSide,
/**
* 两面都渲染
*/
DoubleSide,
}
/**
* 材质基类,一些基本属性加上
*/
export class BaseMaterial extends HashObject {
/**
* 十六进制 hex2rgb ,转成0到1的数组
*/
private _color: number = 0xffffff;
private _colorArr: Float32Array = new Float32Array([1.0, 1.0, 1.0]);
get color() {
return this._color;
}
set color(value: number) {
if (this._color === value) return;
this._color = value;
var arr = hex2rgb(value)
this._colorArr[0] = arr[0];
this._colorArr[1] = arr[1];
this._colorArr[2] = arr[2];
}
//获取
get colorArr() {
return this._colorArr;
}
/**
* 透明度0到1
*/
alpha: number = 1
/**
* 纹理贴图,默认白图
*/
map: Texture = Texture.WHITE;
/**
* 是否用线框形式绘制
*/
wireframe: boolean = false;
side: RenderSideType = RenderSideType.FrontSide;
/**
* 是否光照影响
*/
_lightAffect: boolean = false;
constructor(parameters?) {
super();
this._instanceType = "BaseMaterial";
//所有属性
if (parameters) {
for (var key in parameters) {
this[key] = parameters[key];
}
}
}
destroy() {
this._color = null;
}
}
interface BaseMaterialParamsInt {
color?: number,
alpha?: number,
map?: Texture,
wireframe?: boolean
}
\ No newline at end of file
import { BaseMaterial } from "./BaseMaterial";
export class LightMaterial extends BaseMaterial {
constructor(parameters?) {
super(parameters);
this._instanceType = "LightMaterial";
this._lightAffect = true;
}
}
\ No newline at end of file
import { BaseMaterial, RenderSideType } from "./BaseMaterial";
/**
* 天空盒材质,由于暂时用球做天空盒,所以side设置背面,对应的着色器有修改,深度值最大,且相机距离不影响天空盒
* 还有问题,再说
*/
export class SkyboxMaterial extends BaseMaterial {
constructor(parameters?) {
super(parameters);
this._instanceType = "SkyboxMaterial";
this.side = RenderSideType.BackSide;
}
}
\ No newline at end of file
export * from "./BaseMaterial";
export * from "./LightMaterial";
// export * from "./SkyBoxMaterial";//还有问题
\ No newline at end of file
import { Vector3 } from './Vector3';
import { Sphere } from './Sphere';
import { Object3D } from '../Object3D';
import { Matrix4 } from '../index';
export class Box3 {
constructor(
public min: Vector3 = new Vector3(+ Infinity, + Infinity, + Infinity),
public max: Vector3 = new Vector3(- Infinity, - Infinity, - Infinity)
) { }
set(min: Vector3, max: Vector3) {
this.min.copy(min);
this.max.copy(max);
return this
}
clone() {
return new Box3().copy(this);
}
copy(box: Box3) {
this.min.copy(box.min);
this.max.copy(box.max);
return this;
};
makeEmpty() {
this.min.x = this.min.y = this.min.z = + Infinity;
this.max.x = this.max.y = this.max.z = - Infinity;
return this;
}
isEmpty() {
return (this.max.x < this.min.x) || (this.max.y < this.min.y) || (this.max.z < this.min.z);
}
/**
* 获取中心点
* @param out
*/
getCenter(out: Vector3 = new Vector3()): Vector3 {
return this.isEmpty() ? out.set(0, 0, 0) : out.addVectors(this.min, this.max).multiplyScalar(0.5);
};
/**
* 获取对角线向量
* @param out
*/
getSize(out: Vector3 = new Vector3()): Vector3 {
return this.isEmpty() ? out.set(0, 0, 0) : out.subVectors(this.max, this.min);
};
/**
*
* @param array 一般是顶点一维数组
*/
setFromArray(array: number[] | Float32Array) {
var minX = + Infinity;
var minY = + Infinity;
var minZ = + Infinity;
var maxX = - Infinity;
var maxY = - Infinity;
var maxZ = - Infinity;
for (var i = 0, l = array.length; i < l; i += 3) {
var x = array[i];
var y = array[i + 1];
var z = array[i + 2];
if (x < minX) minX = x;
if (y < minY) minY = y;
if (z < minZ) minZ = z;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
if (z > maxZ) maxZ = z;
}
this.min.set(minX, minY, minZ);
this.max.set(maxX, maxY, maxZ);
return this;
}
setFromCenterAndSize(center: Vector3, size: Vector3) {
var v1 = new Vector3();
var halfSize = v1.copy(size).multiplyScalar(0.5);
this.min.copy(center).sub(halfSize);
this.max.copy(center).add(halfSize);
return this;
}
setFromPoints(points: Vector3[]) {
this.makeEmpty();
for (var i = 0, il = points.length; i < il; i++) {
this.expandByPoint(points[i]);
}
return this;
}
setFromObject(object: Object3D) {
this.makeEmpty();
return this.expandByObject(object);
};
/**
* 为了包含该点坐标
* @param point
*/
expandByPoint(point: Vector3) {
this.min.min(point);
this.max.max(point);
return this;
};
/**
* 为了xyz分别根据vector进行扩展
* @param vector
*/
expandByVector(vector: Vector3) {
this.min.sub(vector);
this.max.add(vector);
return this;
};
expandByScalar(scalar: number) {
this.min.addScalar(- scalar);
this.max.addScalar(scalar);
return this;
};
expandByObject(object: Object3D) {
let scope = this;
var v1 = new Vector3();
object.updateWorldMatrix();
traverse(object);
function traverse(node: Object3D) {
//@ts-ignore 自己的先算
var geometry = node.geometry;
if (geometry !== undefined && geometry._vertices) {
var vertices = geometry._vertices;
for (var i = 0; i < vertices.length; i += 3) {
v1.set(vertices[i], vertices[i + 1], vertices[i + 2]).applyMatrix4(node._worldMatrix);
scope.expandByPoint(v1);
}
}
//子级递归
for (var j = 0; j < node.children.length; j++) traverse(node.children[j]);
}
return scope;
};
containsPoint(point: Vector3) {
return point.x < this.min.x || point.x > this.max.x ||
point.y < this.min.y || point.y > this.max.y ||
point.z < this.min.z || point.z > this.max.z ? false : true;
};
containsBox(box: Box3) {
return this.min.x <= box.min.x && box.max.x <= this.max.x &&
this.min.y <= box.min.y && box.max.y <= this.max.y &&
this.min.z <= box.min.z && box.max.z <= this.max.z;
};
intersectsBox(box: Box3) {
return box.max.x < this.min.x || box.min.x > this.max.x ||
box.max.y < this.min.y || box.min.y > this.max.y ||
box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
};
intersectsSphere(sphere: Sphere) {
var closestPoint = new Vector3();
// Find the point on the AABB closest to the sphere center.
this.clampPoint(sphere.center, closestPoint);
// If that point is inside the sphere, the AABB and sphere intersect.
return closestPoint.distanceToSquared(sphere.center) <= (sphere.radius * sphere.radius);
};
clampPoint(point: Vector3, out: Vector3 = new Vector3()) {
return out.copy(point).clamp(this.min, this.max);
};
distanceToPoint(point: Vector3) {
var v1 = new Vector3();
var clampedPoint = v1.copy(point).clamp(this.min, this.max);
return clampedPoint.sub(point).length();
}
getBoundingSphere(out: Sphere = new Sphere()) {
var v1 = new Vector3();
this.getCenter(out.center);
out.radius = this.getSize(v1).length() * 0.5;
return out;
}
intersect(box: Box3) {
this.min.max(box.min);
this.max.min(box.max);
// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
if (this.isEmpty()) this.makeEmpty();
return this;
}
union(box: Box3) {
this.min.min(box.min);
this.max.max(box.max);
return this;
}
applyMatrix4(matrix: Matrix4) {
var points = [
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
];
// transform of empty box is an empty box.
if (this.isEmpty()) return this;
// NOTE: I am using a binary pattern to specify all 2^3 combinations below
points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix); // 000
points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix); // 001
points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix); // 010
points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix); // 011
points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix); // 100
points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix); // 101
points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix); // 110
points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix); // 111
this.setFromPoints(points);
return this;
}
translate(offset: Vector3) {
this.min.add(offset);
this.max.add(offset);
return this;
}
equals(box: Box3) {
return box.min.equals(this.min) && box.max.equals(this.max);
}
}
import { Quaternion } from './Quaternion';
import { Vector3 } from './Vector3';
import { Matrix4 } from './Matrix4';
import { clamp } from '../../2d/utils';
export enum RotationOrders {
XYZ = "XYZ",
YZX = 'YZX',
ZXY = 'ZXY',
XZY = 'XZY',
YXZ = 'YXZ',
ZYX = 'ZYX'
}
export class Euler {
constructor(
private _x: number = 0,
private _y: number = 0,
private _z: number = 0,
private _order: RotationOrders = RotationOrders.XYZ
) { }
get x(): number {
return this._x;
}
set x(value) {
this._x = value;
this.onChangeCallback();
}
get y() {
return this._y;
}
set y(value) {
this._y = value;
this.onChangeCallback();
}
get z() {
return this._z;
}
set z(value) {
this._z = value;
this.onChangeCallback();
}
get order() {
return this._order;
}
set order(value) {
this._order = value;
this.onChangeCallback();
}
set(x, y, z, order) {
this._x = x;
this._y = y;
this._z = z;
this._order = order || this._order;
this.onChangeCallback();
return this;
}
clone() {
return new Euler(this._x, this._y, this._z, this._order);
}
copy(euler: Euler) {
this._x = euler._x;
this._y = euler._y;
this._z = euler._z;
this._order = euler._order;
this.onChangeCallback();
return this;
}
setFromRotationMatrix(m: Matrix4, order: RotationOrders, update) {
// var clamp = _Math.clamp;
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
var te = m.elements;
var m11 = te[0], m12 = te[4], m13 = te[8];
var m21 = te[1], m22 = te[5], m23 = te[9];
var m31 = te[2], m32 = te[6], m33 = te[10];
order = order || this._order;
if (order === 'XYZ') {
this._y = Math.asin(clamp(m13, - 1, 1));
if (Math.abs(m13) < 0.99999) {
this._x = Math.atan2(- m23, m33);
this._z = Math.atan2(- m12, m11);
} else {
this._x = Math.atan2(m32, m22);
this._z = 0;
}
} else if (order === 'YXZ') {
this._x = Math.asin(- clamp(m23, - 1, 1));
if (Math.abs(m23) < 0.99999) {
this._y = Math.atan2(m13, m33);
this._z = Math.atan2(m21, m22);
} else {
this._y = Math.atan2(- m31, m11);
this._z = 0;
}
} else if (order === 'ZXY') {
this._x = Math.asin(clamp(m32, - 1, 1));
if (Math.abs(m32) < 0.99999) {
this._y = Math.atan2(- m31, m33);
this._z = Math.atan2(- m12, m22);
} else {
this._y = 0;
this._z = Math.atan2(m21, m11);
}
} else if (order === 'ZYX') {
this._y = Math.asin(- clamp(m31, - 1, 1));
if (Math.abs(m31) < 0.99999) {
this._x = Math.atan2(m32, m33);
this._z = Math.atan2(m21, m11);
} else {
this._x = 0;
this._z = Math.atan2(- m12, m22);
}
} else if (order === 'YZX') {
this._z = Math.asin(clamp(m21, - 1, 1));
if (Math.abs(m21) < 0.99999) {
this._x = Math.atan2(- m23, m22);
this._y = Math.atan2(- m31, m11);
} else {
this._x = 0;
this._y = Math.atan2(m13, m33);
}
} else if (order === 'XZY') {
this._z = Math.asin(- clamp(m12, - 1, 1));
if (Math.abs(m12) < 0.99999) {
this._x = Math.atan2(m32, m22);
this._y = Math.atan2(m13, m11);
} else {
this._x = Math.atan2(- m23, m33);
this._y = 0;
}
} else {
console.warn('Euler: .setFromRotationMatrix() given unsupported order: ' + order);
}
this._order = order;
if (update !== false) this.onChangeCallback();
return this;
}
setFromQuaternion = function () {
var matrix = new Matrix4();
return function setFromQuaternion(q:Quaternion, order, update) {
matrix.makeRotationFromQuaternion(q);
return this.setFromRotationMatrix(matrix, order, update);
};
}()
setFromVector3(v, order: RotationOrders) {
return this.set(v.x, v.y, v.z, order || this._order);
}
reorder = function () {
// WARNING: this discards revolution information -bhouston
var q = new Quaternion();
return function reorder(newOrder) {
q.setFromEuler(this);
return this.setFromQuaternion(q, newOrder);
};
}()
equals(euler) {
return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
}
fromArray(array) {
this._x = array[0];
this._y = array[1];
this._z = array[2];
if (array[3] !== undefined) this._order = array[3];
this.onChangeCallback();
return this;
}
toArray(array, offset) {
if (array === undefined) array = [];
if (offset === undefined) offset = 0;
array[offset] = this._x;
array[offset + 1] = this._y;
array[offset + 2] = this._z;
array[offset + 3] = this._order;
return array;
}
toVector3(optionalResult) {
if (optionalResult) {
return optionalResult.set(this._x, this._y, this._z);
} else {
return new Vector3(this._x, this._y, this._z);
}
}
onChange(callback) {
this.onChangeCallback = callback;
return this;
}
onChangeCallback() {
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import { Box3 } from './Box3';
import { Vector3 } from './Vector3';
import { Matrix4 } from './Matrix4';
export class Sphere {
constructor(
public center = new Vector3(),
public radius: number = 0
) { }
set(center: Vector3, radius: number) {
this.center.copy(center);
this.radius = radius;
return this;
}
setFromPoints(points: Vector3[], optionalCenter?: Vector3) {
var box = new Box3();
var center = this.center;
if (optionalCenter !== undefined) {
center.copy(optionalCenter);
} else {
box.setFromPoints(points).getCenter(center);
}
var maxRadiusSq = 0;
for (var i = 0, il = points.length; i < il; i++) {
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
}
this.radius = Math.sqrt(maxRadiusSq);
return this;
}
clone() {
return new Sphere().copy(this);
};
copy(sphere: Sphere) {
this.center.copy(sphere.center);
this.radius = sphere.radius;
return this;
};
empty() {
return (this.radius <= 0);
}
containsPoint(point: Vector3) {
return (point.distanceToSquared(this.center) <= (this.radius * this.radius));
}
distanceToPoint(point: Vector3) {
return (point.distanceTo(this.center) - this.radius);
}
intersectsSphere(sphere: Sphere) {
var radiusSum = this.radius + sphere.radius;
return sphere.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);
};
intersectsBox(box: Sphere) {
return box.intersectsSphere(this);
};
clampPoint(point: Vector3, target: Vector3 = new Vector3()) {
var deltaLengthSq = this.center.distanceToSquared(point);
target.copy(point);
if (deltaLengthSq > (this.radius * this.radius)) {
target.sub(this.center).normalize();
target.multiplyScalar(this.radius).add(this.center);
}
return target;
};
getBoundingBox(target: Box3 = new Box3()) {
target.set(this.center, this.center);
target.expandByScalar(this.radius);
return target;
}
applyMatrix4(matrix: Matrix4) {
this.center.applyMatrix4(matrix);
this.radius = this.radius * matrix.getMaxScaleOnAxis();
return this;
};
translate(offset: Vector3) {
this.center.add(offset);
return this;
};
equals(sphere: Sphere) {
return sphere.center.equals(this.center) && (sphere.radius === this.radius);
}
}
This diff is collapsed.
This diff is collapsed.
import { GLShader } from "../../glCore";
//着色器变量统一驼峰
const baseVert = [
"attribute vec3 aPosition;",//顶点位置信息
"attribute vec3 aColor;",//顶点颜色数据
"attribute vec2 aTextureCoord;",//纹理坐标,
// "attribute vec2 aNormal;",//纹理坐标,
"uniform mat4 uViewMatrix;",//视图矩阵,camera的worldMatrixInverse
"uniform mat4 uProjectionMatrix;",//投影矩阵,camera的projectionMatrix
"uniform mat4 uModelMatrix;",//模型矩阵
// "uniform mat4 uNormalMatrix;",//
"varying vec3 vColor;",//只有颜色数据需要传,或者考虑是否放材质里
"varying vec2 vTextureCoord;",//传到着色器的纹理坐标
"void main() {",
"gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix *vec4(aPosition,1.0);",
"vColor = aColor;",
"vTextureCoord = aTextureCoord;",
"}"
].join("\n")
const baseFrag = [
"precision mediump float;",//片元得加精度
'uniform sampler2D uMap;',//纹理
"uniform vec3 uMatColor;", //材质上的颜色,以后区分发散颜色等等
"uniform float uMatAlpha;", //材质上的透明度
"varying vec3 vColor;",//考虑颜色谁传
"varying vec2 vTextureCoord;",
"void main() {",
//计算纹理颜色
"vec4 mapColor = texture2D(uMap, vTextureCoord);",
//计算顶点颜色
"vec4 color = mapColor *vec4(vColor,1.0);",//叠加顶点颜色和纹理颜色
//计算材质颜色
"vec4 matColor = vec4( uMatColor, uMatAlpha );",
//总颜色
"color *=matColor;",
"gl_FragColor = color;",
"}"
].join("\n")
/**
* 着色器程序根据渲染器的uid和着色器的字符或者自己的id缓存,
* 以后按照材质参数拼着色器
* 纯色的,不带光照的,带贴图的着色器,
*/
export class BaseShader extends GLShader {
/**
* 作为该着色器的标识
*/
_glShaderKey: string;
constructor(gl: WebGLRenderingContext) {
super(gl, baseVert, baseFrag)
this._glShaderKey = "BaseShader";
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export enum ShaderParms {
hasMap = "HasMap",
hasLight = "HasLight",
}
\ No newline at end of file
export * from "./BaseShader"
export * from "./LightShader"
// export * from "./SkyboxShader"
\ No newline at end of file
......@@ -241,7 +241,9 @@ export class VertexArrayObject {
public getSize() {
var attrib = this.attributes[0];
return attrib.buffer.data.length / ((attrib.stride / 4) || attrib.attribute.size);
// return attrib.buffer.data.length / ((attrib.stride / 4) || attrib.attribute.size);
//ArrayBuffer没有length,要不要考虑0?
return (attrib.buffer.data.length || attrib.buffer.data.byteLength / 4) / ((attrib.stride / 4) || attrib.attribute.size);
};
/**
......
......@@ -34,6 +34,9 @@ export * from "./sound"
export * from "./tween";
//3D相关测试
export * from "./3d";
//如果是浏览器环境,声明个my为null,为了无声明不报错
if (window) window["my"] = null
export * from "./Stats";
......
This diff is collapsed.
This diff is collapsed.
test/res/res.png

271 KB | W: | H:

test/res/res.png

500 KB | W: | H:

test/res/res.png
test/res/res.png
test/res/res.png
test/res/res.png
  • 2-up
  • Swipe
  • Onion skin
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment