From c19dfed59d23ce54a29864a288f402eb92104cbd Mon Sep 17 00:00:00 2001 From: lirongf <619213582@qq.com> Date: Fri, 2 Apr 2021 16:12:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0IDE=E7=9A=84=E7=94=BB?= =?UTF-8?q?=E7=BA=BF=20=20pick=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../3d/LayaAirIDE/EditorComponent/GridLine.ts | 99 +++ .../LayaAirIDE/EditorMaterial/GridMaterial.ts | 85 ++ .../EditorSceneManager/Show3DCoordScene.ts | 167 ++++ .../3d/LayaAirIDE/EditorShader/GridLine.fs | 34 + .../3d/LayaAirIDE/EditorShader/GridLine.vs | 25 + .../3d/LayaAirIDE/EditorShader/MeshPick.fs | 18 + .../EditorShader/ParticleShuriKenPick.fs | 48 ++ .../EditorShader/ParticleShuriKenPick.vs | 767 ++++++++++++++++++ .../3d/LayaAirIDE/MeshUtil/MeshEditor.ts | 361 +++++++++ .../MouseInteraction/EditPickUtil.ts | 161 ++++ .../LayaAirIDE/MouseInteraction/PickInit.ts | 94 +++ 11 files changed, 1859 insertions(+) create mode 100644 src/samples/3d/LayaAirIDE/EditorComponent/GridLine.ts create mode 100644 src/samples/3d/LayaAirIDE/EditorMaterial/GridMaterial.ts create mode 100644 src/samples/3d/LayaAirIDE/EditorSceneManager/Show3DCoordScene.ts create mode 100644 src/samples/3d/LayaAirIDE/EditorShader/GridLine.fs create mode 100644 src/samples/3d/LayaAirIDE/EditorShader/GridLine.vs create mode 100644 src/samples/3d/LayaAirIDE/EditorShader/MeshPick.fs create mode 100644 src/samples/3d/LayaAirIDE/EditorShader/ParticleShuriKenPick.fs create mode 100644 src/samples/3d/LayaAirIDE/EditorShader/ParticleShuriKenPick.vs create mode 100644 src/samples/3d/LayaAirIDE/MeshUtil/MeshEditor.ts create mode 100644 src/samples/3d/LayaAirIDE/MouseInteraction/EditPickUtil.ts create mode 100644 src/samples/3d/LayaAirIDE/MouseInteraction/PickInit.ts diff --git a/src/samples/3d/LayaAirIDE/EditorComponent/GridLine.ts b/src/samples/3d/LayaAirIDE/EditorComponent/GridLine.ts new file mode 100644 index 0000000000..4d7f25a546 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/EditorComponent/GridLine.ts @@ -0,0 +1,99 @@ +import { Camera, CameraEventFlags } from "laya/d3/core/Camera"; +import { RenderState } from "laya/d3/core/material/RenderState"; +import { PixelLineMaterial } from "laya/d3/core/pixelLine/PixelLineMaterial"; +import { PixelLineSprite3D } from "laya/d3/core/pixelLine/PixelLineSprite3D"; +import { CommandBuffer } from "laya/d3/core/render/command/CommandBuffer"; +import { Color } from "laya/d3/math/Color"; +import { Vector3 } from "laya/d3/math/Vector3"; +import { GridMaterial } from "../EditorMaterial/GridMaterial"; + + +export class GridLine { + + private gridLineCommand: CommandBuffer; + private axisLineCommand: CommandBuffer; + + constructor(editorCamera: Camera) { + + let gridLineCommand: CommandBuffer = this.gridLineCommand = new CommandBuffer(); + let axisLineCommand: CommandBuffer = this.axisLineCommand = new CommandBuffer(); + + // todo Command buffer rendertexture bug + editorCamera.addCommandBuffer(CameraEventFlags.BeforeImageEffect, gridLineCommand); + editorCamera.addCommandBuffer(CameraEventFlags.BeforeSkyBox, axisLineCommand); + + GridMaterial.__init__(); + + this._buildAxis(axisLineCommand); + this._buildGridLine(gridLineCommand); + } + + private _buildAxis(axisLineCommand: CommandBuffer) { + + let xnum = 200; + let ynum = 200; + let gridw = 10; + let minx = -xnum * gridw; + let miny = -ynum * gridw; + let maxx = xnum * gridw; + let maxy = ynum * gridw; + + let xcolor = new Color(1, 0.5, 0.5, 1.0); + let ycolor = new Color(0.3, 0.8, 0, 0.5); + let zcolor = new Color(0, 0.5, 1, 1.0); + + let axisXZLine: PixelLineSprite3D = new PixelLineSprite3D(2); + axisXZLine.addLine(new Vector3(minx, 0, 0), new Vector3(maxx, 0, 0), xcolor, xcolor); + axisXZLine.addLine(new Vector3(0, 0, minx), new Vector3(0, 0, maxx), zcolor, zcolor); + + let lineXZMaterial: GridMaterial = new GridMaterial(); + lineXZMaterial.step = 100; + axisLineCommand.drawRender(axisXZLine.pixelLineRenderer, lineXZMaterial, 0); + + /* + let axisYLine: PixelLineSprite3D = new PixelLineSprite3D(1); + axisYLine.addLine(new Vector3(0, 0, 0), new Vector3(0, maxy, 0), ycolor, ycolor); + + let lineYMaterial: PixelLineMaterial = new PixelLineMaterial(); + axisLineCommand.drawRender(axisYLine.pixelLineRenderer, lineYMaterial, 0); + */ + } + + private _buildGridLine(gridLineCommand: CommandBuffer) { + let gridLineCount = 10000; + + let gridLine1: PixelLineSprite3D = new PixelLineSprite3D(gridLineCount); + this.addGridLine(gridLine1, 1000, 1); + let gridMaterial1: GridMaterial = new GridMaterial(); + gridMaterial1.step = 1; + + let gridLine10: PixelLineSprite3D = new PixelLineSprite3D(gridLineCount); + this.addGridLine(gridLine10, 1000, 10); + let gridMaterial10: GridMaterial = new GridMaterial(); + gridMaterial10.step = 10; + + let gridLine100: PixelLineSprite3D = new PixelLineSprite3D(gridLineCount); + this.addGridLine(gridLine100, 1000, 100); + let gridMaterial100: GridMaterial = new GridMaterial(); + gridMaterial100.step = 100; + + gridLineCommand.drawRender(gridLine1.pixelLineRenderer, gridMaterial1, 0); + gridLineCommand.drawRender(gridLine10.pixelLineRenderer, gridMaterial10, 0); + gridLineCommand.drawRender(gridLine100.pixelLineRenderer, gridMaterial100, 0); + } + + private addGridLine(line: PixelLineSprite3D, area: number, step: number, color: Color = new Color(0.3, 0.3, 0.3, 1.0)) { + let lineColor: Color = color; + for (let index = -area + step; index < area; index += step) { + if (index != 0) { + var l1: Vector3 = new Vector3(index, 0, -area); + var l2: Vector3 = new Vector3(index, 0, area); + var l3: Vector3 = new Vector3(-area, 0, index); + var l4: Vector3 = new Vector3(area, 0, index); + line.addLine(l1, l2, lineColor, lineColor); + line.addLine(l3, l4, lineColor, lineColor); + } + + } + } +} diff --git a/src/samples/3d/LayaAirIDE/EditorMaterial/GridMaterial.ts b/src/samples/3d/LayaAirIDE/EditorMaterial/GridMaterial.ts new file mode 100644 index 0000000000..6d7c37be11 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/EditorMaterial/GridMaterial.ts @@ -0,0 +1,85 @@ +import { Material } from "laya/d3/core/material/Material"; +import { VertexMesh } from "laya/d3/graphics/Vertex/VertexMesh"; +import { Shader3D } from "laya/d3/shader/Shader3D"; +import { SubShader } from "laya/d3/shader/SubShader"; + +import GridLineVS from "../EditorShader/GridLine.vs"; +import GridLineFS from "../EditorShader/GridLine.fs"; + +import { ShaderPass } from "laya/d3/shader/ShaderPass"; +import { RenderState } from "laya/d3/core/material/RenderState"; +import { Vector4 } from "laya/d3/math/Vector4"; + +export class GridMaterial extends Material { + + static COLOR: number = Shader3D.propertyNameToID("u_Color"); + static STEP: number = Shader3D.propertyNameToID("u_Step"); + + static __init__(): void { + var attributeMap: any = { + 'a_Position': VertexMesh.MESH_POSITION0, + 'a_Color': VertexMesh.MESH_COLOR0 + }; + + var uniformMap: any = { + 'u_MvpMatrix': Shader3D.PERIOD_SPRITE, + + 'u_View': Shader3D.PERIOD_CAMERA, + 'u_CameraPos': Shader3D.PERIOD_CAMERA, + + 'u_Color': Shader3D.PERIOD_MATERIAL, + 'u_Step': Shader3D.PERIOD_MATERIAL // todo 位置 + }; + + var shader: Shader3D = Shader3D.add("_GridShader", attributeMap, uniformMap, false, false); + var subShader: SubShader = new SubShader(attributeMap, uniformMap); + shader.addSubShader(subShader); + var shaderPass: ShaderPass = subShader.addShaderPass(GridLineVS, GridLineFS); + + shaderPass.renderState.depthWrite = false; + shaderPass.renderState.blend = RenderState.BLEND_ENABLE_ALL; + shaderPass.renderState.srcBlend = RenderState.BLENDPARAM_SRC_ALPHA; + shaderPass.renderState.dstBlend = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA; + shaderPass.renderState.depthTest = RenderState.DEPTHTEST_LESS; + } + + /** + * 获取颜色。 + * @return 颜色。 + */ + get color(): Vector4 { + return (this._shaderValues.getVector(GridMaterial.COLOR)); + } + + /** + * 设置颜色。 + * @param value 颜色。 + */ + set color(value: Vector4) { + this._shaderValues.setVector(GridMaterial.COLOR, value); + } + + /** + * + */ + set step(value: number) { + this._shaderValues.setNumber(GridMaterial.STEP, value); + } + + get step(): number { + return this._shaderValues.getNumber(GridMaterial.STEP); + } + + constructor() { + super(); + this.setShaderName("_GridShader"); + this._shaderValues.setNumber(GridMaterial.STEP, 10); + this._shaderValues.setVector(GridMaterial.COLOR, new Vector4(1.0, 1.0, 1.0, 1.0)); + } + + clone(): any { + var dest: GridMaterial = new GridMaterial(); + this.cloneTo(dest); + return dest; + } +} \ No newline at end of file diff --git a/src/samples/3d/LayaAirIDE/EditorSceneManager/Show3DCoordScene.ts b/src/samples/3d/LayaAirIDE/EditorSceneManager/Show3DCoordScene.ts new file mode 100644 index 0000000000..200fb2cc4f --- /dev/null +++ b/src/samples/3d/LayaAirIDE/EditorSceneManager/Show3DCoordScene.ts @@ -0,0 +1,167 @@ +import { Laya } from "Laya"; +import { Camera } from "laya/d3/core/Camera"; +import { UnlitMaterial } from "laya/d3/core/material/UnlitMaterial"; +import { MeshSprite3D } from "laya/d3/core/MeshSprite3D"; +import { Scene3D } from "laya/d3/core/scene/Scene3D"; +import { Vector3 } from "laya/d3/math/Vector3"; +import { Event } from "laya/events/Event"; +import { RenderTexture } from "laya/d3/resource/RenderTexture"; +import { RenderTextureDepthFormat, RenderTextureFormat } from "laya/resource/RenderTextureFormat"; +import { Texture } from "laya/resource/Texture"; +import { Box } from "laya/ui/Box"; +import { Image } from "laya/ui/Image"; +import { Handler } from "laya/utils/Handler"; +import { CameraControlScript, IDE_RotateDirectFlags } from "../EditorComponent/CameraControlScript"; +import { BillboardMaterial } from "../EditorMaterial/BillboardMaterial"; +import { Vector4 } from "laya/d3/math/Vector4"; +import { EditPickUtil } from "../MouseInteraction/EditPickUtil"; +import { Script3D } from "laya/d3/component/Script3D"; +import { Sprite } from "laya/display/Sprite"; + +/** + * miner 用来显示旋转小场景 + */ +export class Show3DCoordScene extends Script3D{ + static CoordImageSize:number = 100; + static pickRect:number =5; + static CheckColorFZ:Vector4 = new Vector4(44,144,255,255); + static CheckColorZZ:Vector4 = new Vector4(40,144,255,255); + static CheckColorFX:Vector4 = new Vector4(247,52,100,255); + static CheckColorZX:Vector4 = new Vector4(247,52,81,255); + static CheckColorFY:Vector4 = new Vector4(135,212,2,255); + static CheckColorZY:Vector4 = new Vector4(135,212,3,255); + + pickColorArray:Uint8Array = new Uint8Array((Show3DCoordScene.pickRect*2+1)*(Show3DCoordScene.pickRect*2+1)*4); + //小坐标场景 + coord3DScene:Scene3D; + //图标相机 + tubiaoCamera:Camera; + //图标相机贴图 + tubiaoTarget:RenderTexture; + //图标Image + showImage:Image; + //主场景相机控制器 + cameraControl:CameraControlScript; + //主场景panel + parent:Sprite; + //@private + private _tempVec:Vector3 = new Vector3(); + + constructor(){ + super(); + } + + init(cameraControl:CameraControlScript,parent:Sprite){ + // + this.cameraControl = cameraControl; + this.parent = parent; + //开启鼠标点击事件 + Laya.stage.on(Event.MOUSE_DOWN,this,this.mouseDown); + + Scene3D.load("res/3DEditorResource/LayaScene_tubiao/Conventional/tubiao.ls",Handler.create(this,function(scene:Scene3D):void{ + Laya.stage.addChild(scene); + this.Coord3DScene = scene; + var camera = (scene.getChildByName("Main Camera")); + camera.clearColor = new Vector4(0.0,0.0,0.0,0.0); + camera.viewport.width=Show3DCoordScene.CoordImageSize; + camera.viewport.height = Show3DCoordScene.CoordImageSize; + camera.orthographic = true; + camera.orthographicVerticalSize = 8; + this.tubiaoCamera = camera; + camera.enableHDR = false; + this.tubiaoTarget = camera.renderTarget = RenderTexture.createFromPool(Show3DCoordScene.CoordImageSize,Show3DCoordScene.CoordImageSize,RenderTextureFormat.R8G8B8A8,RenderTextureDepthFormat.DEPTH_16); + var tubiaoSprite = scene.getChildByName("tubiao"); + //切换图标材质 + for(let i = 0;i<6;i++){ + var currentMat:UnlitMaterial; + var transMat:BillboardMaterial; + currentMat = (tubiaoSprite.getChildAt(i) as MeshSprite3D).meshRenderer.sharedMaterial; + transMat = new BillboardMaterial(); + transMat.renderMode = BillboardMaterial.RENDERMODE_TRANSPARENT; + transMat.alphaTestValue = 0.5; + transMat.albedoTexture = currentMat.albedoTexture; + (tubiaoSprite.getChildAt(i) as MeshSprite3D).meshRenderer.sharedMaterial = transMat; + } + this.addImage(); + })); + } + + + + addImage(){ + this.showImage = new Image(); + + this.showImage.source = new Texture(this.tubiaoTarget); + this.parent.addChild(this.showImage); + this.showImage.top = 10; + this.showImage.right = 10; + //Laya.timer.frameLoop(1,this,this.tongbuCameraDir); + } + onUpdate(){ + this.tongbuCameraDir(); + } + tongbuCameraDir(){ + //@ts-ignore + if(this.tubiaoCamera) + //@ts-ignore + CameraControlScript.calByIcoXYZ(Vector3._ZERO,this._tempVec,10,this.cameraControl.currentRotate,this.tubiaoCamera); + + } + + + mouseDown(e:Event){ + var x = Laya.stage.mouseX; + var y = Laya.stage.mouseY; + if(x>this.showImage.x&&xthis.showImage.y&&y0.1) + gl_FragColor = u_PickColor; + else + discard; +} \ No newline at end of file diff --git a/src/samples/3d/LayaAirIDE/EditorShader/ParticleShuriKenPick.vs b/src/samples/3d/LayaAirIDE/EditorShader/ParticleShuriKenPick.vs new file mode 100644 index 0000000000..82a10a2d65 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/EditorShader/ParticleShuriKenPick.vs @@ -0,0 +1,767 @@ +#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了 + precision highp float; + precision highp int; +#else + precision mediump float; + precision mediump int; +#endif + +#if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD) + attribute vec4 a_CornerTextureCoordinate; +#endif +#ifdef RENDERMODE_MESH + attribute vec3 a_MeshPosition; + attribute vec4 a_MeshColor; + attribute vec2 a_MeshTextureCoordinate; + varying vec4 v_MeshColor; +#endif + +attribute vec4 a_ShapePositionStartLifeTime; +attribute vec4 a_DirectionTime; +attribute vec4 a_StartColor; +attribute vec3 a_StartSize; +attribute vec3 a_StartRotation0; +attribute float a_StartSpeed; +#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)||defined(ROTATIONOVERLIFETIMERANDOMCURVES) + attribute vec4 a_Random0; +#endif +#if defined(TEXTURESHEETANIMATIONRANDOMCURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + attribute vec4 a_Random1; +#endif +attribute vec3 a_SimulationWorldPostion; +attribute vec4 a_SimulationWorldRotation; + +varying float v_Discard; +varying vec4 v_Color; +#ifdef DIFFUSEMAP + varying vec2 v_TextureCoordinate; +#endif + +uniform float u_CurrentTime; +uniform vec3 u_Gravity; + +uniform vec3 u_WorldPosition; +uniform vec4 u_WorldRotation; +uniform bool u_ThreeDStartRotation; +uniform int u_ScalingMode; +uniform vec3 u_PositionScale; +uniform vec3 u_SizeScale; +uniform mat4 u_View; +uniform mat4 u_Projection; + +#ifdef STRETCHEDBILLBOARD + uniform vec3 u_CameraPosition; +#endif +uniform vec3 u_CameraDirection;//TODO:只有几种广告牌模式需要用 +uniform vec3 u_CameraUp; + +uniform float u_StretchedBillboardLengthScale; +uniform float u_StretchedBillboardSpeedScale; +uniform int u_SimulationSpace; + +#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + uniform int u_VOLSpaceType; +#endif +#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT) + uniform vec3 u_VOLVelocityConst; +#endif +#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + uniform vec2 u_VOLVelocityGradientX[4];//x为key,y为速度 + uniform vec2 u_VOLVelocityGradientY[4];//x为key,y为速度 + uniform vec2 u_VOLVelocityGradientZ[4];//x为key,y为速度 +#endif +#ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT + uniform vec3 u_VOLVelocityConstMax; +#endif +#ifdef VELOCITYOVERLIFETIMERANDOMCURVE + uniform vec2 u_VOLVelocityGradientMaxX[4];//x为key,y为速度 + uniform vec2 u_VOLVelocityGradientMaxY[4];//x为key,y为速度 + uniform vec2 u_VOLVelocityGradientMaxZ[4];//x为key,y为速度 +#endif + +#ifdef COLOROVERLIFETIME + uniform vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color + uniform vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha +#endif +#ifdef RANDOMCOLOROVERLIFETIME + uniform vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color + uniform vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha + uniform vec4 u_MaxColorOverLifeGradientColors[4];//x为key,yzw为Color + uniform vec2 u_MaxColorOverLifeGradientAlphas[4];//x为key,y为Alpha +#endif + + +#if defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMERANDOMCURVES) + uniform vec2 u_SOLSizeGradient[4];//x为key,y为尺寸 +#endif +#ifdef SIZEOVERLIFETIMERANDOMCURVES + uniform vec2 u_SOLSizeGradientMax[4];//x为key,y为尺寸 +#endif +#if defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE) + uniform vec2 u_SOLSizeGradientX[4];//x为key,y为尺寸 + uniform vec2 u_SOLSizeGradientY[4];//x为key,y为尺寸 + uniform vec2 u_SOLSizeGradientZ[4];//x为key,y为尺寸 +#endif +#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE + uniform vec2 u_SOLSizeGradientMaxX[4];//x为key,y为尺寸 + uniform vec2 u_SOLSizeGradientMaxY[4];//x为key,y为尺寸 + uniform vec2 u_SOLSizeGradientMaxZ[4];//x为key,y为尺寸 +#endif + + +#ifdef ROTATIONOVERLIFETIME + #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS) + uniform float u_ROLAngularVelocityConst; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + uniform float u_ROLAngularVelocityConstMax; + #endif + #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES) + uniform vec2 u_ROLAngularVelocityGradient[4];//x为key,y为旋转 + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + uniform vec2 u_ROLAngularVelocityGradientMax[4];//x为key,y为旋转 + #endif +#endif +#ifdef ROTATIONOVERLIFETIMESEPERATE + #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS) + uniform vec3 u_ROLAngularVelocityConstSeprarate; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + uniform vec3 u_ROLAngularVelocityConstMaxSeprarate; + #endif + #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES) + uniform vec2 u_ROLAngularVelocityGradientX[4]; + uniform vec2 u_ROLAngularVelocityGradientY[4]; + uniform vec2 u_ROLAngularVelocityGradientZ[4]; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + uniform vec2 u_ROLAngularVelocityGradientMaxX[4]; + uniform vec2 u_ROLAngularVelocityGradientMaxY[4]; + uniform vec2 u_ROLAngularVelocityGradientMaxZ[4]; + uniform vec2 u_ROLAngularVelocityGradientMaxW[4]; + #endif +#endif + +#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE) + uniform float u_TSACycles; + uniform vec2 u_TSASubUVLength; + uniform vec2 u_TSAGradientUVs[4];//x为key,y为frame +#endif +#ifdef TEXTURESHEETANIMATIONRANDOMCURVE + uniform vec2 u_TSAMaxGradientUVs[4];//x为key,y为frame +#endif + + +#ifdef TILINGOFFSET + uniform vec4 u_TilingOffset; +#endif + +vec3 rotationByEuler(in vec3 vector,in vec3 rot) +{ + float halfRoll = rot.z * 0.5; + float halfPitch = rot.x * 0.5; + float halfYaw = rot.y * 0.5; + + float sinRoll = sin(halfRoll); + float cosRoll = cos(halfRoll); + float sinPitch = sin(halfPitch); + float cosPitch = cos(halfPitch); + float sinYaw = sin(halfYaw); + float cosYaw = cos(halfYaw); + + float quaX = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll); + float quaY = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll); + float quaZ = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll); + float quaW = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll); + + //vec4 q=vec4(quaX,quaY,quaZ,quaW); + //vec3 temp = cross(q.xyz, vector) + q.w * vector; + //return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp); + + float x = quaX + quaX; + float y = quaY + quaY; + float z = quaZ + quaZ; + float wx = quaW * x; + float wy = quaW * y; + float wz = quaW * z; + float xx = quaX * x; + float xy = quaX * y; + float xz = quaX * z; + float yy = quaY * y; + float yz = quaY * z; + float zz = quaZ * z; + + return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)), + ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)), + ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy))); + +} + +//假定axis已经归一化 +vec3 rotationByAxis(in vec3 vector,in vec3 axis, in float angle) +{ + float halfAngle = angle * 0.5; + float sin = sin(halfAngle); + + float quaX = axis.x * sin; + float quaY = axis.y * sin; + float quaZ = axis.z * sin; + float quaW = cos(halfAngle); + + //vec4 q=vec4(quaX,quaY,quaZ,quaW); + //vec3 temp = cross(q.xyz, vector) + q.w * vector; + //return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp); + + float x = quaX + quaX; + float y = quaY + quaY; + float z = quaZ + quaZ; + float wx = quaW * x; + float wy = quaW * y; + float wz = quaW * z; + float xx = quaX * x; + float xy = quaX * y; + float xz = quaX * z; + float yy = quaY * y; + float yz = quaY * z; + float zz = quaZ * z; + + return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)), + ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)), + ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy))); + +} + +vec3 rotationByQuaternions(in vec3 v,in vec4 q) +{ + return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); +} + + +#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE) +float getCurValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge) +{ + float curValue; + for(int i=1;i<4;i++) + { + vec2 gradientNumber=gradientNumbers[i]; + float key=gradientNumber.x; + if(key>=normalizedAge) + { + vec2 lastGradientNumber=gradientNumbers[i-1]; + float lastKey=lastGradientNumber.x; + float age=(normalizedAge-lastKey)/(key-lastKey); + curValue=mix(lastGradientNumber.y,gradientNumber.y,age); + break; + } + } + return curValue; +} +#endif + +#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES) +float getTotalValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge) +{ + float totalValue=0.0; + for(int i=1;i<4;i++) + { + vec2 gradientNumber=gradientNumbers[i]; + float key=gradientNumber.x; + vec2 lastGradientNumber=gradientNumbers[i-1]; + float lastValue=lastGradientNumber.y; + + if(key>=normalizedAge){ + float lastKey=lastGradientNumber.x; + float age=(normalizedAge-lastKey)/(key-lastKey); + totalValue+=(lastValue+mix(lastValue,gradientNumber.y,age))/2.0*a_ShapePositionStartLifeTime.w*(normalizedAge-lastKey); + break; + } + else{ + totalValue+=(lastValue+gradientNumber.y)/2.0*a_ShapePositionStartLifeTime.w*(key-lastGradientNumber.x); + } + } + return totalValue; +} +#endif + +#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME) +vec4 getColorFromGradient(in vec2 gradientAlphas[4],in vec4 gradientColors[4],in float normalizedAge) +{ + vec4 overTimeColor; + for(int i=1;i<4;i++) + { + vec2 gradientAlpha=gradientAlphas[i]; + float alphaKey=gradientAlpha.x; + if(alphaKey>=normalizedAge) + { + vec2 lastGradientAlpha=gradientAlphas[i-1]; + float lastAlphaKey=lastGradientAlpha.x; + float age=(normalizedAge-lastAlphaKey)/(alphaKey-lastAlphaKey); + overTimeColor.a=mix(lastGradientAlpha.y,gradientAlpha.y,age); + break; + } + } + + for(int i=1;i<4;i++) + { + vec4 gradientColor=gradientColors[i]; + float colorKey=gradientColor.x; + if(colorKey>=normalizedAge) + { + vec4 lastGradientColor=gradientColors[i-1]; + float lastColorKey=lastGradientColor.x; + float age=(normalizedAge-lastColorKey)/(colorKey-lastColorKey); + overTimeColor.rgb=mix(gradientColors[i-1].yzw,gradientColor.yzw,age); + break; + } + } + return overTimeColor; +} +#endif + + +#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE) +float getFrameFromGradient(in vec2 gradientFrames[4],in float normalizedAge) +{ + float overTimeFrame; + for(int i=1;i<4;i++) + { + vec2 gradientFrame=gradientFrames[i]; + float key=gradientFrame.x; + if(key>=normalizedAge) + { + vec2 lastGradientFrame=gradientFrames[i-1]; + float lastKey=lastGradientFrame.x; + float age=(normalizedAge-lastKey)/(key-lastKey); + overTimeFrame=mix(lastGradientFrame.y,gradientFrame.y,age); + break; + } + } + return floor(overTimeFrame); +} +#endif + +#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) +vec3 computeParticleLifeVelocity(in float normalizedAge) +{ + vec3 outLifeVelocity; + #ifdef VELOCITYOVERLIFETIMECONSTANT + outLifeVelocity=u_VOLVelocityConst; + #endif + #ifdef VELOCITYOVERLIFETIMECURVE + outLifeVelocity= vec3(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge)); + #endif + #ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT + outLifeVelocity=mix(u_VOLVelocityConst,u_VOLVelocityConstMax,vec3(a_Random1.y,a_Random1.z,a_Random1.w)); + #endif + #ifdef VELOCITYOVERLIFETIMERANDOMCURVE + outLifeVelocity=vec3(mix(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y), + mix(getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z), + mix(getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w)); + #endif + + return outLifeVelocity; +} +#endif + +vec3 computeParticlePosition(in vec3 startVelocity, in vec3 lifeVelocity,in float age,in float normalizedAge,vec3 gravityVelocity,vec4 worldRotation) +{ + vec3 startPosition; + vec3 lifePosition; + #if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + #ifdef VELOCITYOVERLIFETIMECONSTANT + startPosition=startVelocity*age; + lifePosition=lifeVelocity*age; + #endif + #ifdef VELOCITYOVERLIFETIMECURVE + startPosition=startVelocity*age; + lifePosition=vec3(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge)); + #endif + #ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT + startPosition=startVelocity*age; + lifePosition=lifeVelocity*age; + #endif + #ifdef VELOCITYOVERLIFETIMERANDOMCURVE + startPosition=startVelocity*age; + lifePosition=vec3(mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y) + ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z) + ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w)); + #endif + + vec3 finalPosition; + if(u_VOLSpaceType==0){ + if(u_ScalingMode!=2) + finalPosition =rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition),worldRotation); + else + finalPosition =rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition,worldRotation); + } + else{ + if(u_ScalingMode!=2) + finalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation)+lifePosition; + else + finalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation)+lifePosition; + } + #else + startPosition=startVelocity*age; + vec3 finalPosition; + if(u_ScalingMode!=2) + finalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation); + else + finalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation); + #endif + + if(u_SimulationSpace==0) + finalPosition=finalPosition+a_SimulationWorldPostion; + else if(u_SimulationSpace==1) + finalPosition=finalPosition+u_WorldPosition; + + finalPosition+=0.5*gravityVelocity*age; + + return finalPosition; +} + + +vec4 computeParticleColor(in vec4 color,in float normalizedAge) +{ + #ifdef COLOROVERLIFETIME + color*=getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge); + #endif + + #ifdef RANDOMCOLOROVERLIFETIME + color*=mix(getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge),getColorFromGradient(u_MaxColorOverLifeGradientAlphas,u_MaxColorOverLifeGradientColors,normalizedAge),a_Random0.y); + #endif + + return color; +} + +vec2 computeParticleSizeBillbard(in vec2 size,in float normalizedAge) +{ + #ifdef SIZEOVERLIFETIMECURVE + size*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge); + #endif + #ifdef SIZEOVERLIFETIMERANDOMCURVES + size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); + #endif + #ifdef SIZEOVERLIFETIMECURVESEPERATE + size*=vec2(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge)); + #endif + #ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE + size*=vec2(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z) + ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z)); + #endif + return size; +} + +#ifdef RENDERMODE_MESH +vec3 computeParticleSizeMesh(in vec3 size,in float normalizedAge) +{ + #ifdef SIZEOVERLIFETIMECURVE + size*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge); + #endif + #ifdef SIZEOVERLIFETIMERANDOMCURVES + size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); + #endif + #ifdef SIZEOVERLIFETIMECURVESEPERATE + size*=vec3(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge)); + #endif + #ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE + size*=vec3(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z) + ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z) + ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxZ,normalizedAge),a_Random0.z)); + #endif + return size; +} +#endif + +float computeParticleRotationFloat(in float rotation,in float age,in float normalizedAge) +{ + #ifdef ROTATIONOVERLIFETIME + #ifdef ROTATIONOVERLIFETIMECONSTANT + float ageRot=u_ROLAngularVelocityConst*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMECURVE + rotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge); + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + float ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + rotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w); + #endif + #endif + #ifdef ROTATIONOVERLIFETIMESEPERATE + #ifdef ROTATIONOVERLIFETIMECONSTANT + float ageRot=u_ROLAngularVelocityConstSeprarate.z*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMECURVE + rotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge); + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + float ageRot=mix(u_ROLAngularVelocityConstSeprarate.z,u_ROLAngularVelocityConstMaxSeprarate.z,a_Random0.w)*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + rotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w)); + #endif + #endif + return rotation; +} + +#if defined(RENDERMODE_MESH)&&(defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE)) +vec3 computeParticleRotationVec3(in vec3 rotation,in float age,in float normalizedAge) +{ + #ifdef ROTATIONOVERLIFETIME + #ifdef ROTATIONOVERLIFETIMECONSTANT + float ageRot=u_ROLAngularVelocityConst*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMECURVE + rotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge); + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + float ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + rotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w); + #endif + #endif + #ifdef ROTATIONOVERLIFETIMESEPERATE + #ifdef ROTATIONOVERLIFETIMECONSTANT + vec3 ageRot=u_ROLAngularVelocityConstSeprarate*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMECURVE + rotation+=vec3(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge)); + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS + vec3 ageRot=mix(u_ROLAngularVelocityConstSeprarate,u_ROLAngularVelocityConstMaxSeprarate,a_Random0.w)*age; + rotation+=ageRot; + #endif + #ifdef ROTATIONOVERLIFETIMERANDOMCURVES + rotation+=vec3(mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxX,normalizedAge),a_Random0.w) + ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxY,normalizedAge),a_Random0.w) + ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w)); + #endif + #endif + return rotation; +} +#endif + +vec2 computeParticleUV(in vec2 uv,in float normalizedAge) +{ + #ifdef TEXTURESHEETANIMATIONCURVE + float cycleNormalizedAge=normalizedAge*u_TSACycles; + float frame=getFrameFromGradient(u_TSAGradientUVs,cycleNormalizedAge-floor(cycleNormalizedAge)); + float totalULength=frame*u_TSASubUVLength.x; + float floorTotalULength=floor(totalULength); + uv.x+=totalULength-floorTotalULength; + uv.y+=floorTotalULength*u_TSASubUVLength.y; + #endif + #ifdef TEXTURESHEETANIMATIONRANDOMCURVE + float cycleNormalizedAge=normalizedAge*u_TSACycles; + float uvNormalizedAge=cycleNormalizedAge-floor(cycleNormalizedAge); + float frame=floor(mix(getFrameFromGradient(u_TSAGradientUVs,uvNormalizedAge),getFrameFromGradient(u_TSAMaxGradientUVs,uvNormalizedAge),a_Random1.x)); + float totalULength=frame*u_TSASubUVLength.x; + float floorTotalULength=floor(totalULength); + uv.x+=totalULength-floorTotalULength; + uv.y+=floorTotalULength*u_TSASubUVLength.y; + #endif + return uv; +} + +void main() +{ + float age = u_CurrentTime - a_DirectionTime.w; + float normalizedAge = age/a_ShapePositionStartLifeTime.w; + vec3 lifeVelocity; + if(normalizedAge<1.0){ + vec3 startVelocity=a_DirectionTime.xyz*a_StartSpeed; + #if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + lifeVelocity= computeParticleLifeVelocity(normalizedAge);//计算粒子生命周期速度 + #endif + vec3 gravityVelocity=u_Gravity*age; + + vec4 worldRotation; + if(u_SimulationSpace==0) + worldRotation=a_SimulationWorldRotation; + else + worldRotation=u_WorldRotation; + + vec3 center=computeParticlePosition(startVelocity, lifeVelocity, age, normalizedAge,gravityVelocity,worldRotation);//计算粒子位置 + + + #ifdef SPHERHBILLBOARD + vec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效 + vec3 cameraUpVector =normalize(u_CameraUp);//TODO:是否外面归一化 + vec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector)); + vec3 upVector = normalize(cross(sideVector,u_CameraDirection)); + corner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge); + #if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE) + if(u_ThreeDStartRotation){ + vec3 rotation=vec3(a_StartRotation0.xy,computeParticleRotationFloat(a_StartRotation0.z,age,normalizedAge)); + center += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,rotation); + } + else{ + float rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge); + float c = cos(rot); + float s = sin(rot); + mat2 rotation= mat2(c, -s, s, c); + corner=rotation*corner; + center += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector); + } + #else + if(u_ThreeDStartRotation){ + center += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,a_StartRotation0); + } + else{ + float c = cos(a_StartRotation0.x); + float s = sin(a_StartRotation0.x); + mat2 rotation= mat2(c, -s, s, c); + corner=rotation*corner; + center += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector); + } + #endif + #endif + + #ifdef STRETCHEDBILLBOARD + vec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效 + vec3 velocity; + #if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE) + if(u_VOLSpaceType==0) + velocity=rotationByQuaternions(u_SizeScale*(startVelocity+lifeVelocity),worldRotation)+gravityVelocity; + else + velocity=rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+lifeVelocity+gravityVelocity; + #else + velocity= rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+gravityVelocity; + #endif + vec3 cameraUpVector = normalize(velocity); + vec3 direction = normalize(center-u_CameraPosition); + vec3 sideVector = normalize(cross(direction,normalize(velocity))); + + sideVector=u_SizeScale.xzy*sideVector; + cameraUpVector=length(vec3(u_SizeScale.x,0.0,0.0))*cameraUpVector; + + vec2 size=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge); + + const mat2 rotaionZHalfPI=mat2(0.0, -1.0, 1.0, 0.0); + corner=rotaionZHalfPI*corner; + corner.y=corner.y-abs(corner.y); + + float speed=length(velocity);//TODO: + center +=sign(u_SizeScale.x)*(sign(u_StretchedBillboardLengthScale)*size.x*corner.x*sideVector+(speed*u_StretchedBillboardSpeedScale+size.y*u_StretchedBillboardLengthScale)*corner.y*cameraUpVector); + #endif + + #ifdef HORIZONTALBILLBOARD + vec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效 + const vec3 cameraUpVector=vec3(0.0,0.0,1.0); + const vec3 sideVector = vec3(-1.0,0.0,0.0); + + float rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge); + float c = cos(rot); + float s = sin(rot); + mat2 rotation= mat2(c, -s, s, c); + corner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因 + corner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge); + center +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector); + #endif + + #ifdef VERTICALBILLBOARD + vec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效 + const vec3 cameraUpVector =vec3(0.0,1.0,0.0); + vec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector)); + + float rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge); + float c = cos(rot); + float s = sin(rot); + mat2 rotation= mat2(c, -s, s, c); + corner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因 + corner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge); + center +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector); + #endif + + #ifdef RENDERMODE_MESH + vec3 size=computeParticleSizeMesh(a_StartSize,normalizedAge); + #if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE) + if(u_ThreeDStartRotation){ + vec3 rotation=vec3(a_StartRotation0.xy,-computeParticleRotationFloat(a_StartRotation0.z, age,normalizedAge)); + center+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,rotation),worldRotation); + } + else{ + #ifdef ROTATIONOVERLIFETIME + float angle=computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge); + if(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){ + center+= (rotationByQuaternions(rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),angle),worldRotation));//已验证 + } + else{ + #ifdef SHAPE + center+= u_SizeScale.xzy*(rotationByQuaternions(rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),angle),worldRotation)); + #else + if(u_SimulationSpace==0) + center+=rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle);//已验证 + else if(u_SimulationSpace==1) + center+=rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle),worldRotation);//已验证 + #endif + } + #endif + #ifdef ROTATIONOVERLIFETIMESEPERATE + //TODO:是否应合并if(u_ThreeDStartRotation)分支代码,待测试 + vec3 angle=computeParticleRotationVec3(vec3(0.0,0.0,a_StartRotation0.z), age,normalizedAge); + center+= (rotationByQuaternions(rotationByEuler(u_SizeScale*a_MeshPosition*size,vec3(angle.x,angle.y,angle.z)),worldRotation));//已验证 + #endif + } + #else + if(u_ThreeDStartRotation){ + center+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,a_StartRotation0),worldRotation);//已验证 + } + else{ + if(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){ + if(u_SimulationSpace==0) + center+= rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x); + else if(u_SimulationSpace==1) + center+= (rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x),worldRotation));//已验证 + } + else{ + #ifdef SHAPE + if(u_SimulationSpace==0) + center+= u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x); + else if(u_SimulationSpace==1) + center+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x),worldRotation); + #else + if(u_SimulationSpace==0) + center+= rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x); + else if(u_SimulationSpace==1) + center+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x),worldRotation);//已验证 + #endif + } + } + #endif + v_MeshColor=a_MeshColor; + #endif + + gl_Position=u_Projection*u_View*vec4(center,1.0); + v_Color = computeParticleColor(a_StartColor, normalizedAge); + #ifdef DIFFUSEMAP + #if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD) + v_TextureCoordinate =computeParticleUV(a_CornerTextureCoordinate.zw, normalizedAge); + #endif + #ifdef RENDERMODE_MESH + v_TextureCoordinate =computeParticleUV(a_MeshTextureCoordinate, normalizedAge); + #endif + + #ifdef TILINGOFFSET + v_TextureCoordinate=vec2(v_TextureCoordinate.x,1.0-v_TextureCoordinate.y)*u_TilingOffset.xy+vec2(u_TilingOffset.z,-u_TilingOffset.w);//需要特殊处理 + v_TextureCoordinate=vec2(v_TextureCoordinate.x,1.0-v_TextureCoordinate.y);//需要特殊处理 + #endif + #endif + v_Discard=0.0; + } + else + { + v_Discard=1.0; + } +} + diff --git a/src/samples/3d/LayaAirIDE/MeshUtil/MeshEditor.ts b/src/samples/3d/LayaAirIDE/MeshUtil/MeshEditor.ts new file mode 100644 index 0000000000..78dcf245d6 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/MeshUtil/MeshEditor.ts @@ -0,0 +1,361 @@ +// import { Mesh } from "laya/d3/resource/models/Mesh"; +// import { Vector3 } from "laya/d3/math/Vector3"; +// import { Vector2 } from "laya/d3/math/Vector2"; +// import { Vector4 } from "laya/d3/math/Vector4"; +// import { IndexBuffer3D } from "laya/d3/graphics/IndexBuffer3D"; +// import { VertexBuffer3D } from "laya/d3/graphics/VertexBuffer3D"; +// import { VertexDeclaration } from "laya/d3/graphics/VertexDeclaration"; +// import { VertexMesh } from "laya/d3/graphics/Vertex/VertexMesh"; +// import { VertexElement } from "laya/d3/graphics/VertexElement"; +// import { VertexElementFormat } from "laya/d3/graphics/VertexElementFormat"; +// import { LayaGL } from "laya/layagl/LayaGL"; +// import { SubMesh } from "laya/d3/resource/models/SubMesh"; +// import { PrimitiveMesh } from "laya/d3/resource/models/PrimitiveMesh"; +// import { MeshSprite3D } from "laya/d3/core/MeshSprite3D"; +// import { AssetsManager, AssetType } from "../../core/assetsmgr/AssetsManager"; +// import { RenderableSprite3D } from "laya/d3/core/RenderableSprite3D"; +// import { MeshFilter } from "laya/d3/core/MeshFilter"; +// import { SkinnedMeshSprite3D } from "laya/d3/core/SkinnedMeshSprite3D"; + +// export class MeshEditor { + +// private static tempV3_0 = new Vector3(); +// private static tempV3_1 = new Vector3(); + + +// static init(){ +// let assetManager = AssetsManager.inst; + +// let mesh = PrimitiveMesh.createBox(); +// let tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultCube",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createCapsule(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultCapsule",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createCone(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultCone",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createCylinder(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultCylinder",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createPlane(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultPlane",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createQuad(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultQuad",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// mesh = PrimitiveMesh.createSphere(); +// tArray = this.calculateTangent(mesh); +// assetManager.addAssets("defaultSphere",AssetType.MESH,MeshEditor.addVertexElement(mesh,VertexMesh.MESH_TANGENT0,tArray)); + +// } + +// /** +// * +// * @param elementUsage +// */ +// static getElementFlagByUsage(elementUsage: number): string { +// switch (elementUsage) { +// case VertexMesh.MESH_POSITION0: +// return "POSITION"; +// case VertexMesh.MESH_NORMAL0: +// return "NORMAL"; +// case VertexMesh.MESH_COLOR0: +// return "COLOR"; +// case VertexMesh.MESH_TEXTURECOORDINATE0: +// return "UV"; +// case VertexMesh.MESH_TEXTURECOORDINATE1: +// return "UV1"; +// case VertexMesh.MESH_BLENDWEIGHT0: +// return "BLENDWEIGHT"; +// case VertexMesh.MESH_BLENDINDICES0: +// return "BLENDINDICES"; +// case VertexMesh.MESH_TANGENT0: +// return "TANGENT"; +// default: +// throw "MeshEditor: unknown vertex flag."; +// } +// } + +// /** +// * 获取 VertexDeclaration 对象 对应的 declaration string +// * @param verDec +// */ +// static getVertexDecStr(verDec: VertexDeclaration): string { + +// let decStrs: string[] = []; + +// let elementCount = verDec.vertexElementCount; +// for (let index = 0; index < elementCount; index++) { +// let e = verDec.getVertexElementByIndex(index); +// let flag: string = MeshEditor.getElementFlagByUsage(e.elementUsage); +// decStrs.push(flag); +// } + +// if (decStrs.length) { +// return decStrs.toString(); +// } +// else { +// return null; +// } +// } + +// static addVertexDeclaration(vertexDeclaration: VertexDeclaration, ) { + +// } + +// /** +// * 向 mesh 中添加新的 vertexElement +// * 若 mesh 中已经存在elementUsage对应元素, 直接返回不进行操作 +// * @param mesh +// * @param elementUsage +// * @param elementData +// */ +// static addVertexElement(mesh: Mesh, elementUsage: number, elementData: Float32Array) { +// let gl: WebGLRenderingContext = LayaGL.instance; + +// let indexBuffer: IndexBuffer3D = mesh._indexBuffer; +// let vertexBuffer: VertexBuffer3D = mesh._vertexBuffer; + +// // 原始 顶点声明 +// let vbDec: VertexDeclaration = mesh.getVertexDeclaration(); + +// // 判断当前 mesh 中是否存在此 element +// // 存在直接返回 +// if (vbDec.getVertexElementByUsage(elementUsage)) { +// return mesh; +// } + +// let compatible = false; +// let boneIndexVE: VertexElement = vbDec.getVertexElementByUsage(VertexMesh.MESH_BLENDINDICES0); +// if (boneIndexVE) { +// compatible = boneIndexVE.elementFormat == VertexElementFormat.Vector4; +// } +// // 生成的新 VertexDeclaration 确保需要添加的数据在顶点结构结尾 +// let vbDecStr: string = MeshEditor.getVertexDecStr(vbDec); +// let flagStr: string = MeshEditor.getElementFlagByUsage(elementUsage); +// vbDecStr += `,${flagStr}`; +// let newvbDec: VertexDeclaration = VertexMesh.getVertexDeclaration(vbDecStr, compatible); + +// let newStride: number = newvbDec.vertexStride; +// let newFloatStride: number = newStride / 4; +// let vertexCount: number = mesh.vertexCount; +// let vertexStride: number = vbDec.vertexStride; +// let vertexFloatStride: number = vertexStride / 4; +// let vertexfloat32: Float32Array = vertexBuffer.getFloat32Data(); +// let newVertexfloat32: Float32Array = new Float32Array(vertexCount * newStride / 4); + +// let addVE: VertexElement = newvbDec.getVertexElementByUsage(elementUsage); +// let addFloatOffset = addVE.offset / 4; +// let elmentInfo: number[] = VertexElementFormat.getElementInfos(addVE.elementFormat); +// let elementLength = (elmentInfo[1] == gl.UNSIGNED_BYTE) ? 1 : 4; + +// for (let index = 0; index < vertexCount; index++) { +// let oriOffset: number = vertexFloatStride * index; +// let offset: number = newFloatStride * index; +// let eoffset: number = offset + addFloatOffset; +// let addDataOffset: number = elementLength * index; +// for (let oi = 0; oi < vertexFloatStride; oi++) { +// newVertexfloat32[offset + oi] = vertexfloat32[oriOffset + oi]; +// } +// for (let i = 0; i < elementLength; i++) { +// newVertexfloat32[eoffset + i] = elementData[addDataOffset + i]; +// } +// } + +// let newVB: VertexBuffer3D = new VertexBuffer3D(newVertexfloat32.byteLength, gl.STATIC_DRAW, true); +// newVB.vertexDeclaration = newvbDec; +// newVB.setData(newVertexfloat32.buffer); +// mesh._vertexBuffer = newVB; +// mesh._setBuffer(newVB, indexBuffer); +// mesh._setInstanceBuffer(mesh._instanceBufferStateType); + +// for (let index = 0; index < mesh.subMeshCount; index++) { +// let subMesh: SubMesh = mesh.getSubMesh(index); +// subMesh._vertexBuffer = newVB; +// } + +// let memorySize: number = newVB._byteLength + indexBuffer._byteLength; + +// mesh._setCPUMemory(memorySize); +// mesh._setGPUMemory(memorySize); + +// return mesh; +// } + + +// /** +// * 计算 mesh tangent 数据 +// * @param mesh +// */ +// static calculateTangent(mesh: Mesh): Float32Array { + +// if (!mesh._isReadable) { +// return null; +// } + +// let vbDec: VertexDeclaration = mesh.getVertexDeclaration(); +// if (!(vbDec.getVertexElementByUsage(VertexMesh.MESH_POSITION0) && vbDec.getVertexElementByUsage(VertexMesh.MESH_NORMAL0) && vbDec.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0))) { +// return null; +// } + +// let indices: Uint32Array = new Uint32Array(mesh.getIndices()); + +// let positions: Vector3[] = []; +// mesh.getPositions(positions); + +// let normals: Vector3[] = []; +// mesh.getNormals(normals); + +// let uvs: Vector2[] = []; +// mesh.getUVs(uvs, 0); + +// let tan1s: Vector3[] = new Array(indices.length); +// for (let index = 0; index < tan1s.length; index++) { +// tan1s[index] = new Vector3(); +// } +// let tan2s: Vector3[] = new Array(indices.length); +// for (let index = 0; index < tan2s.length; index++) { +// tan2s[index] = new Vector3(); +// } + +// for (let i = 0; i < indices.length; i += 3) { +// let index1: number = indices[i]; +// let index2: number = indices[i + 1]; +// let index3: number = indices[i + 2]; + +// let p1: Vector3 = positions[index1]; +// let p2: Vector3 = positions[index2]; +// let p3: Vector3 = positions[index3]; + +// let uv1: Vector2 = uvs[index1]; +// let uv2: Vector2 = uvs[index2]; +// let uv3: Vector2 = uvs[index3]; + +// let x1 = p2.x - p1.x; +// let x2 = p3.x - p1.x; +// let y1 = p2.y - p1.y; +// let y2 = p3.y - p1.y; +// let z1 = p2.z - p1.z; +// let z2 = p3.z - p1.z; + +// let s1 = uv2.x - uv1.x; +// let s2 = uv3.x - uv1.x; +// let t1 = uv2.y - uv1.y; +// let t2 = uv3.y - uv1.y; + +// let r = 1.0 / (s1 * t2 - s2 * t1); +// let sdir: Vector3 = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); +// let tdir: Vector3 = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); + +// Vector3.add(sdir, tan1s[index1], tan1s[index1]); +// Vector3.add(sdir, tan1s[index2], tan1s[index2]); +// Vector3.add(sdir, tan1s[index3], tan1s[index3]); + +// Vector3.add(tdir, tan2s[index1], tan2s[index1]); +// Vector3.add(tdir, tan2s[index2], tan2s[index2]); +// Vector3.add(tdir, tan2s[index3], tan2s[index3]); +// } + +// // let tangents: Vector4[] = []; +// let tangentArray: Float32Array = new Float32Array(mesh.vertexCount * 4); + +// for (let index = 0; index < positions.length; index++) { +// let n: Vector3 = normals[index]; +// let t: Vector3 = tan1s[index]; + +// let temp: Vector3 = MeshEditor.tempV3_0; +// Vector3.scale(n, Vector3.dot(n, t), temp); +// Vector3.subtract(t, temp, temp); +// Vector3.normalize(temp, temp); + +// let temp1: Vector3 = MeshEditor.tempV3_1; +// Vector3.cross(n, t, temp1); +// let w = Vector3.dot(temp1, tan2s[index]) < 0 ? -1 : 1; + +// tangentArray[index * 4] = temp.x; +// tangentArray[index * 4 + 1] = temp.y; +// tangentArray[index * 4 + 2] = temp.z; +// tangentArray[index * 4 + 3] = w; +// // tangents.push(new Vector4(temp.x, temp.y, temp.z, w)); +// } + +// return tangentArray; +// } + +// /** +// * // todo need ? +// * 获取 渲染节点需要的材质个数 +// * @param sprite +// * @returns +// */ +// static getMaterialCount(sprite: MeshSprite3D | SkinnedMeshSprite3D): number { +// let meshFilter: MeshFilter = sprite.meshFilter; +// let mesh: Mesh = meshFilter.sharedMesh; + +// return mesh.subMeshCount; +// } + +// //------------------------------------------------- +// // todo 提出去 +// /** +// * 编辑器生成Box +// */ +// static createBox():MeshSprite3D { +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultCube")); +// } + +// /** +// * miner +// * 编辑器生成Capsule +// */ +// static createCapsule(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultCube")); +// } + +// /** +// * miner +// * 编辑器生成Cone +// */ +// static createCone(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultCone")); +// } + +// /** +// * miner +// * 编辑器生成Cylinder +// */ +// static createCylinder(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultCylinder")); +// } + +// /** +// * miner +// * 编辑器生成Plane +// */ +// static createPlane(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultPlane")); +// } + +// /** +// * miner +// * 编辑器生成Quad +// */ +// static creatQuad(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultQuad")); +// } + +// /** +// * miner +// * 编辑器生成Sphere +// */ +// static createSphere(){ +// return new MeshSprite3D(AssetsManager.inst.getMesh("defaultSphere")); +// } +// } diff --git a/src/samples/3d/LayaAirIDE/MouseInteraction/EditPickUtil.ts b/src/samples/3d/LayaAirIDE/MouseInteraction/EditPickUtil.ts new file mode 100644 index 0000000000..8676214b45 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/MouseInteraction/EditPickUtil.ts @@ -0,0 +1,161 @@ +import { Camera, CameraClearFlags } from "laya/d3/core/Camera"; +import { RenderContext3D } from "laya/d3/core/render/RenderContext3D"; +import { RenderableSprite3D } from "laya/d3/core/RenderableSprite3D"; +import { Scene3D } from "laya/d3/core/scene/Scene3D"; +import { Sprite3D } from "laya/d3/core/Sprite3D"; +import { Vector4 } from "laya/d3/math/Vector4"; +import { Viewport } from "laya/d3/math/Viewport"; +import { RenderTexture } from "laya/d3/resource/RenderTexture"; +import { RenderTextureDepthFormat, RenderTextureFormat } from "laya/resource/RenderTextureFormat"; + + + +/** + * 编辑器拾取方法库 + * @author miner + */ +export class EditPickUtil { + public static selectSprite: Sprite3D; + public static editorCamera: Camera; + public static pickCamera: Camera; + public static editorScene: Scene3D; + public static pickPixel: Uint8Array = new Uint8Array(4); + public static pickVector4: Vector4 = new Vector4(); + public static oriClearFlag: CameraClearFlags = CameraClearFlags.Nothing; + public static oriClearColor: Vector4 = new Vector4(); + public static cameraClearColor: Vector4 = new Vector4(); + public static oriPipeLineMode:string; + + /** + * 设置点选目标 + * @param scene 点选scene + * @param camera 点选Camera + */ + public static setPickTarget(scene: Scene3D, camera: Camera) { + EditPickUtil.editorCamera = camera; + EditPickUtil.editorScene = scene; + if (!EditPickUtil.pickCamera) { + EditPickUtil.pickCamera = new Camera(); + EditPickUtil.pickCamera.name = "pick Camera"; + } + //@ts-ignore + EditPickUtil.oriPipeLineMode = RenderContext3D._instance.configPipeLineMode; + } + + + /** + * 选中的渲染节点 + * @param posX 相对位置x + * @param posY 相对位置y + * @param texture 点选图片 + */ + private static pickRenderableSprite3D(posX: number, posY: number, texture: RenderTexture): RenderableSprite3D { + var pixelArray = EditPickUtil.pickPixel; + var pickVec = EditPickUtil.pickVector4; + var scene = EditPickUtil.editorScene; + texture.getData(posX, posY, 1, 1, EditPickUtil.pickPixel); + console.log(this.pickPixel); + pickVec.setValue(pixelArray[0], pixelArray[1], pixelArray[2], pixelArray[3]); + //@ts-ignore + var id = scene._searchIDByPickColor(pickVec); + //@ts-ignore + return scene._pickIdToSprite[id]; + } + + + static pickRenderTextureColor(posX: number, posY: number, texture: RenderTexture, outPixelArray: Uint8Array, reck: number) { + texture.getData(posX - reck, posY - reck, reck * 2 + 1, reck * 2 + 1, outPixelArray); + } + + /** + * 获得选中的物体 + * @param posX 绝对鼠标位置x + * @param posY 绝对鼠标位置y + * @param offsetX 图片偏移x + * @param offsetY 图片偏移y + * @param n 范围容错 + */ + public static pickSelectSprite3D(posX: number, posY: number, offsetX: number = 0, offsetY: number = 0, n: number = 1): Sprite3D { + var camera = EditPickUtil.editorCamera; + if (posX < 0 || posY < 0 || !camera) return; + //@ts-ignore + var context = RenderContext3D._instance; + //切换渲染pass + //var pipeLineModeMode = context.pipelineMode; + context.configPipeLineMode = "PickSprite"; + EditPickUtil.recordCameraData(camera); + //渲染节点 + + (!EditPickUtil.pickCamera) && (EditPickUtil.pickCamera.renderTarget = RenderTexture.createFromPool(camera.renderTarget.width, camera.renderTarget.height, RenderTextureFormat.R8G8B8A8, RenderTextureDepthFormat.DEPTH_16)) + var RT: RenderTexture = Camera.drawRenderTextureByScene(EditPickUtil.pickCamera, EditPickUtil.editorScene, EditPickUtil.pickCamera.renderTarget); + + var renderableSprite = EditPickUtil.pickRenderableSprite3D(posX - offsetX, posY - offsetY, RT); + if (renderableSprite) + EditPickUtil.selectSprite = renderableSprite; + //还原渲染pass + context.configPipeLineMode = EditPickUtil.oriPipeLineMode; + return renderableSprite; + } + + /** + * 记录camera原始数据,设置pick数据 + * @param camera + */ + public static recordCameraData(camera: Camera) { + + var pickCamera: Camera = EditPickUtil.pickCamera; + pickCamera.farPlane = camera.farPlane; + pickCamera.nearPlane = camera.nearPlane; + pickCamera.transform.worldMatrix = camera.transform.worldMatrix; + pickCamera.aspectRatio = camera.aspectRatio; + pickCamera.orthographic = camera.orthographic; + + if (pickCamera.orthographic) { + pickCamera.orthographicVerticalSize = camera.orthographicVerticalSize; + } + pickCamera.clearFlag = CameraClearFlags.SolidColor; + pickCamera.clearColor = EditPickUtil.cameraClearColor; + } + + + + /** + * 框选精灵队列 + */ + public static pickSprite3DsByRect(): Array { + return null; + } + + + /** + * 重新设置摄像机 + * @param camera + * @param width 宽度 + * @param height 高度 + */ + public static EditorCameraSet(camera: Camera, width: number, height: number,isOriCamraRenderTarget = true): void { + var oriTargetTexture: RenderTexture = camera.renderTarget; + var pickTargetTexture: RenderTexture = EditPickUtil.pickCamera.renderTarget; + if (!oriTargetTexture) { + isOriCamraRenderTarget&& (oriTargetTexture = camera.renderTarget = new RenderTexture(width, height, RenderTextureFormat.R8G8B8A8, RenderTextureDepthFormat.DEPTH_16,4)); + if (!pickTargetTexture) + pickTargetTexture = EditPickUtil.pickCamera.renderTarget = new RenderTexture(width, height, RenderTextureFormat.R8G8B8A8, RenderTextureDepthFormat.DEPTH_16); + } + if (oriTargetTexture&&oriTargetTexture.width == width && oriTargetTexture.height == height) { + return; + } + else { + //这里用对象池会内存吃紧 + oriTargetTexture&&oriTargetTexture.destroy(); + pickTargetTexture && pickTargetTexture.destroy(); + oriTargetTexture&&(camera.renderTarget = new RenderTexture(width, height, RenderTextureFormat.R8G8B8A8, RenderTextureDepthFormat.DEPTH_16,4)); + EditPickUtil.pickCamera.renderTarget = new RenderTexture(width, height, RenderTextureFormat.R8G8B8A8, RenderTextureDepthFormat.DEPTH_16); + + camera.render(); + //这里可以是 + camera.viewport = new Viewport(0, 0, width, height); + } + } + + +} \ No newline at end of file diff --git a/src/samples/3d/LayaAirIDE/MouseInteraction/PickInit.ts b/src/samples/3d/LayaAirIDE/MouseInteraction/PickInit.ts new file mode 100644 index 0000000000..3b68d92f69 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/MouseInteraction/PickInit.ts @@ -0,0 +1,94 @@ +import { DefineDatas } from "laya/d3/shader/DefineDatas"; +import { Shader3D } from "laya/d3/shader/Shader3D"; +import { ShaderPass } from "laya/d3/shader/ShaderPass"; +import { SubShader } from "laya/d3/shader/SubShader"; +import { ShaderNode } from "laya/webgl/utils/ShaderNode"; +import MeshPick from "../EditorShader/MeshPick.fs"; +import ShurikenPickVS from "../EditorShader/ParticleShuriKenPick.vs"; +import ShurikenPickFS from "../EditorShader/ParticleShuriKenPick.fs"; + +/** + * 为所有的Shader 添加Pass + * @author miner + */ +export class PickInit{ + + static shader3DCompileShader:any; + /** + * 初始化 + */ + static Init():void{ + //@ts-ignore + PickInit.shader3DCompileShader= Shader3D._preCompileShader; + PickInit.addPickShaderPath(); + } + + /** + * 给所有的SubShader添加PickSprite渲染pass + * 每增加一个自定义的shader 都需要重新调用一下 + */ + static addPickShaderPath():void{ + var shader; + var shaderMap; + var shaderName; + var subShaders; + var subShader; + var i,n; + shaderMap =PickInit.shader3DCompileShader; + for(var index in shaderMap){ + shader = shaderMap[index] as Shader3D; + shaderName = shader.name; + //@ts-ignore + subShaders = shader._subShaders; + for(i = 0,n = subShaders.length;i Date: Fri, 2 Apr 2021 16:15:17 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0pickIDE=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/samples/3d/LayaAirIDE/Main/PickIDE.ts | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/samples/3d/LayaAirIDE/Main/PickIDE.ts diff --git a/src/samples/3d/LayaAirIDE/Main/PickIDE.ts b/src/samples/3d/LayaAirIDE/Main/PickIDE.ts new file mode 100644 index 0000000000..a6f87e4351 --- /dev/null +++ b/src/samples/3d/LayaAirIDE/Main/PickIDE.ts @@ -0,0 +1,43 @@ +import { Laya } from "Laya"; +import { Camera } from "laya/d3/core/Camera"; +import { Scene3D } from "laya/d3/core/scene/Scene3D"; +import { Sprite3D } from "laya/d3/core/Sprite3D"; +import { Vector3 } from "laya/d3/math/Vector3"; +import { Stage } from "laya/display/Stage"; +import { Loader } from "laya/net/Loader"; +import { Handler } from "laya/utils/Handler"; +import { Stat } from "laya/utils/Stat"; +import { Laya3D } from "Laya3D"; + +export class PickIDE { + + private scene: Scene3D; + + constructor() { + //初始化引擎 + Laya3D.init(0, 0); + Laya.stage.scaleMode = Stage.SCALE_FULL; + Laya.stage.screenMode = Stage.SCREEN_NONE; + //显示性能面板 + Stat.show(); + + this.scene = (Laya.stage.addChild(new Scene3D())); + this.scene.ambientColor = new Vector3(1, 1, 1); + + var camera: Camera = (this.scene.addChild(new Camera(0, 0.1, 100))); + camera.transform.translate(new Vector3(0, 0.5, 1)); + camera.transform.rotate(new Vector3(-15, 0, 0), true, false); + + Laya.loader.create("res/threeDimen/skinModel/LayaMonkey/LayaMonkey.lh", Handler.create(this, this.onComplete)); + } + + onComplete(): void { + + var layaMonkey: Sprite3D = (this.scene.addChild(Loader.getRes("res/threeDimen/skinModel/LayaMonkey/LayaMonkey.lh"))); + //克隆sprite3d + var layaMonkey_clone1: Sprite3D = Sprite3D.instantiate(layaMonkey, this.scene, false, new Vector3(0.6, 0, 0)); + //克隆sprite3d + var layaMonkey_clone2: Sprite3D = (this.scene.addChild(Sprite3D.instantiate(layaMonkey, null, false, new Vector3(-0.6, 0, 0)))); + } +} +