@@ -12,36 +12,44 @@ import { useDark } from '@vueuse/core'
1212import { ElMessage } from ' element-plus'
1313// @ts-ignore
1414import Stats from ' stats.js'
15+ // @ts-ignore
16+ import particleFire from ' three-particle-fire' ;
17+ try { particleFire .install ( { THREE: THREE } ); } catch (e ) { }
1518
1619const container = ref <HTMLDivElement | null >(null )
1720const pitch = ref (0 )
1821const roll = ref (0 )
1922const yaw = ref (0 )
20- const currentModel = ref (' arrow ' )
23+ const currentModel = ref (' rocket ' )
2124const customModel = ref <THREE .Group | null >(null )
2225const fileInput = ref <HTMLInputElement | null >(null )
2326
2427const isDark = useDark ()
2528const sceneBackground = computed (() => isDark .value ? 0x1a1a1a : 0xf0f0f0 )
2629// const gridColor = computed(() => isDark.value ? 0x404040 : 0x808080)
27- const modelColor = computed (() => isDark .value ? 0x4a9eff : 0x3366ff )
30+ const modelColor = computed (() => isDark .value ? 0x404040 : 0x3366ff )
31+ // const modelColor = computed(() => isDark.value ? 0xF4F5F0 : 0x3366ff)
2832
2933let scene: THREE .Scene
34+ let clock: THREE .Clock
3035let camera: THREE .PerspectiveCamera
3136let renderer: THREE .WebGLRenderer
3237let model: THREE .Group
3338let controls: OrbitControls
3439let animationFrameId: number
3540let stats: Stats
41+ let rocketFireMesh: any
3642
3743const initScene = () => {
3844 scene = new THREE .Scene ()
3945 scene .background = new THREE .Color (sceneBackground .value )
4046
4147 // 添加坐标轴辅助器
42- const axesHelper = new THREE .AxesHelper (5 )
48+ const axesHelper = new THREE .AxesHelper (1.6 )
4349 scene .add (axesHelper )
4450
51+ clock = new THREE .Clock ()
52+
4553 // 初始化性能监视器
4654 stats = new Stats ()
4755 stats .showPanel (0 ) // 0: fps, 1: ms, 2: mb, 3+: custom
@@ -98,6 +106,50 @@ const createArrowModel = () => {
98106 return group
99107}
100108
109+ const createRocketModel = () => {
110+ const group = new THREE .Group ()
111+
112+ // 箭头主体
113+ const bodyGeometry = new THREE .ConeGeometry (0.2 , 0.5 , 12 )
114+ const bodyMaterial = new THREE .MeshStandardMaterial ({
115+ color: modelColor .value ,
116+ metalness: 0.6 ,
117+ roughness: 0.3 ,
118+ envMapIntensity: 1.2
119+ })
120+ const body = new THREE .Mesh (bodyGeometry , bodyMaterial )
121+ body .position .set (0 , 1.05 , 0 )
122+ // body.rotation.x = -Math.PI / 2
123+ group .add (body )
124+
125+ const tailGeometry = new THREE .CylinderGeometry (0.2 , 0.2 , 1.6 )
126+ const tailMaterial = new THREE .MeshStandardMaterial ({
127+ color: modelColor .value ,
128+ metalness: 0.6 ,
129+ roughness: 0.3 ,
130+ envMapIntensity: 1.2
131+ })
132+ const tail = new THREE .Mesh (tailGeometry , tailMaterial )
133+ tail .position .set (0 , 0 , 0 )
134+ group .add (tail )
135+
136+ const fireRadius = 0.09 ;
137+ const fireHeight = 1.5 ;
138+ const particleCount = 800 ;
139+ const height = window .innerHeight ;
140+
141+ const geometry0 = new particleFire .Geometry ( fireRadius , fireHeight , particleCount );
142+ const material0 = new particleFire .Material ( { color: 0xff2200 } );
143+ material0 .setPerspective ( camera .fov , height );
144+ rocketFireMesh = new THREE .Points ( geometry0 , material0 );
145+ rocketFireMesh .rotation .x = 3.14
146+ rocketFireMesh .position .set (0 , - 0.92 , 0 )
147+
148+ group .add (rocketFireMesh )
149+
150+ return group
151+ }
152+
101153const createCubeModel = () => {
102154 const group = new THREE .Group ()
103155
@@ -120,6 +172,9 @@ const createModel = (type: string) => {
120172 }
121173
122174 switch (type ) {
175+ case ' rocket' :
176+ model = createRocketModel ()
177+ break
123178 case ' arrow' :
124179 model = createArrowModel ()
125180 break
@@ -205,6 +260,7 @@ const addLights = () => {
205260}
206261
207262const animate = () => {
263+ var delta = clock .getDelta ();
208264 animationFrameId = requestAnimationFrame (animate )
209265 stats .begin ()
210266
@@ -215,6 +271,9 @@ const animate = () => {
215271 THREE .MathUtils .degToRad (pitch .value )
216272 )
217273 }
274+ if (rocketFireMesh ) {
275+ rocketFireMesh .material .update ( delta );
276+ }
218277
219278 controls .update ()
220279 renderer .render (scene , camera )
@@ -223,9 +282,15 @@ const animate = () => {
223282
224283const handleResize = () => {
225284 if (container .value && camera && renderer ) {
226- camera .aspect = container .value .clientWidth / container .value .clientHeight
285+ let width = container .value .clientWidth
286+ let height = container .value .clientHeight
287+ camera .aspect = width / height
227288 camera .updateProjectionMatrix ()
228- renderer .setSize (container .value .clientWidth , container .value .clientHeight )
289+ renderer .setSize (width , height )
290+
291+ if (rocketFireMesh ) {
292+ rocketFireMesh .material .setPerspective ( camera .fov , height );
293+ }
229294 }
230295}
231296
0 commit comments