mirror of https://github.com/almqv/wych.dev
parent
ae1a514854
commit
ac4b24e4a2
@ -1,82 +1,82 @@ |
|||||||
"use client"; |
"use client"; |
||||||
|
|
||||||
import * as THREE from "three"; |
import * as THREE from "three"; |
||||||
import { CurveProps } from "../renderer"; |
import { CurveProps } from "../renderer"; |
||||||
|
|
||||||
const maxParticles = 20000; |
const maxParticles = 20000; |
||||||
|
|
||||||
const startScatter = 0.1; |
const startScatter = 0.1; |
||||||
|
|
||||||
const init = () => { |
const init = () => { |
||||||
var arrayCurve = []; |
var arrayCurve = []; |
||||||
|
|
||||||
var x = 0.01, |
var x = 0.01, |
||||||
y = 0.01, |
y = 0.01, |
||||||
z = 0.01; |
z = 0.01; |
||||||
var a = 0.9; |
var a = 0.9; |
||||||
var b = 3.4; |
var b = 3.4; |
||||||
var f = 9.9; |
var f = 9.9; |
||||||
var g = 1; |
var g = 1; |
||||||
var t = 0.001; |
var t = 0.001; |
||||||
for (var i = 0; i < maxParticles; i++) { |
for (var i = 0; i < maxParticles; i++) { |
||||||
x = x - t * a * x + t * y * y - t * z * z + t * a * f; |
x = x - t * a * x + t * y * y - t * z * z + t * a * f; |
||||||
y = y - t * y + t * x * y - t * b * x * z + t * g; |
y = y - t * y + t * x * y - t * b * x * z + t * g; |
||||||
z = z - t * z + t * b * x * y + t * x * z; |
z = z - t * z + t * b * x * y + t * x * z; |
||||||
arrayCurve.push( |
arrayCurve.push( |
||||||
new THREE.Vector3(x, y, z).multiplyScalar( |
new THREE.Vector3(x, y, z).multiplyScalar( |
||||||
1 - startScatter / 2 + Math.random() * startScatter, |
1 - startScatter / 2 + Math.random() * startScatter, |
||||||
), |
), |
||||||
); |
); |
||||||
} |
} |
||||||
return arrayCurve; |
return arrayCurve; |
||||||
}; |
}; |
||||||
|
|
||||||
const update = (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => { |
const update = (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => { |
||||||
//Varying the points on each frame
|
//Varying the points on each frame
|
||||||
// step += 0.01;
|
// step += 0.01;
|
||||||
var geometry = pc.geometry; |
var geometry = pc.geometry; |
||||||
var a = 0.9; //+ Math.random() * .2;
|
var a = 0.9; //+ Math.random() * .2;
|
||||||
var b = 3.4; //+ Math.random() * .1;
|
var b = 3.4; //+ Math.random() * .1;
|
||||||
var f = 9.9; //+ Math.random() * .2;
|
var f = 9.9; //+ Math.random() * .2;
|
||||||
var g = 1; //+ Math.random() * .1;
|
var g = 1; //+ Math.random() * .1;
|
||||||
var t = 0.001; |
var t = 0.001; |
||||||
|
|
||||||
var positions = geometry.attributes.position; |
var positions = geometry.attributes.position; |
||||||
const numPoints = positions.array.length / 3; |
const numPoints = positions.array.length / 3; |
||||||
|
|
||||||
for (let i = 0; i < numPoints; i++) { |
for (let i = 0; i < numPoints; i++) { |
||||||
let x = positions.getX(i), |
let x = positions.getX(i), |
||||||
y = positions.getY(i), |
y = positions.getY(i), |
||||||
z = positions.getZ(i); |
z = positions.getZ(i); |
||||||
positions.setXYZ( |
positions.setXYZ( |
||||||
i, |
i, |
||||||
x - t * a * x + t * y * y - t * z * z + t * a * f, |
x - t * a * x + t * y * y - t * z * z + t * a * f, |
||||||
y - t * y + t * x * y - t * b * x * z + t * g, |
y - t * y + t * x * y - t * b * x * z + t * g, |
||||||
z - t * z + t * b * x * y + t * x * z, |
z - t * z + t * b * x * y + t * x * z, |
||||||
); |
); |
||||||
} |
} |
||||||
positions.needsUpdate = true; |
positions.needsUpdate = true; |
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
// group.rotation.x += 0.0005;
|
// group.rotation.x += 0.0005;
|
||||||
// group.rotation.y += 0.001;
|
// group.rotation.y += 0.001;
|
||||||
// group.rotation.z -= 0.0005;
|
// group.rotation.z -= 0.0005;
|
||||||
}; |
}; |
||||||
|
|
||||||
// INFO: Curve definition
|
// INFO: Curve definition
|
||||||
const ThingCurve = { |
const ThingCurve = { |
||||||
func: { init: init, update: update }, |
func: { init: init, update: update }, |
||||||
cam: { |
cam: { |
||||||
pos: new THREE.Vector3(0, 0, 18).multiplyScalar(1.7), |
pos: new THREE.Vector3(0, 0, 18).multiplyScalar(1.7), |
||||||
rotation: new THREE.Vector3(0, 0, 180), |
rotation: new THREE.Vector3(0, 0, 180), |
||||||
}, |
}, |
||||||
particles: { |
particles: { |
||||||
max: maxParticles, |
max: maxParticles, |
||||||
size: 0.07, |
size: 0.07, |
||||||
color: "#888", |
color: "#888", |
||||||
darkcolor: "#444", |
darkcolor: "#444", |
||||||
opacity: 0.4, |
opacity: 0.4, |
||||||
}, // 87a
|
}, // 87a
|
||||||
}; |
}; |
||||||
|
|
||||||
export default ThingCurve; |
export default ThingCurve; |
||||||
|
@ -1,34 +1,34 @@ |
|||||||
"use client"; |
"use client"; |
||||||
|
|
||||||
import React, { ReactNode, HTMLProps } from "react"; |
import React, { ReactNode, HTMLProps } from "react"; |
||||||
import Renderer, { CurveProps } from "@/components/3d/renderer"; |
import Renderer, { CurveProps } from "@/components/3d/renderer"; |
||||||
import { cn } from "@/lib/utils"; |
import { cn } from "@/lib/utils"; |
||||||
|
|
||||||
const RenderedSection: React.FC< |
const RenderedSection: React.FC< |
||||||
HTMLProps<HTMLElement> & { |
HTMLProps<HTMLElement> & { |
||||||
children?: ReactNode; |
children?: ReactNode; |
||||||
evenly?: boolean; |
evenly?: boolean; |
||||||
curve: CurveProps; |
curve: CurveProps; |
||||||
curveClassname?: string; |
curveClassname?: string; |
||||||
} |
} |
||||||
> = ({ |
> = ({ |
||||||
children, |
children, |
||||||
className, |
className, |
||||||
curveClassname, |
curveClassname, |
||||||
evenly = false, |
evenly = false, |
||||||
curve, |
curve, |
||||||
...props |
...props |
||||||
}) => { |
}) => { |
||||||
return ( |
return ( |
||||||
<div className="flex w-full h-full flex-col items-center align-middle relative"> |
<div className="flex w-full h-full flex-col items-center align-middle relative"> |
||||||
<div className={cn("absolute", curveClassname)}> |
<div className={cn("absolute", curveClassname)}> |
||||||
<Renderer {...curve} /> |
<Renderer {...curve} /> |
||||||
</div> |
</div> |
||||||
<section className={cn("relative", className)} {...props}> |
<section className={cn("relative", className)} {...props}> |
||||||
{children} |
{children} |
||||||
</section> |
</section> |
||||||
</div> |
</div> |
||||||
); |
); |
||||||
}; |
}; |
||||||
|
|
||||||
export default RenderedSection; |
export default RenderedSection; |
||||||
|
@ -1,114 +1,114 @@ |
|||||||
"use client"; |
"use client"; |
||||||
|
|
||||||
import * as THREE from "three"; |
import * as THREE from "three"; |
||||||
import React, { ComponentPropsWithRef, useEffect, useRef } from "react"; |
import React, { ComponentPropsWithRef, useEffect, useRef } from "react"; |
||||||
import { Canvas, useFrame, useThree } from "@react-three/fiber"; |
import { Canvas, useFrame, useThree } from "@react-three/fiber"; |
||||||
import { useTheme } from "next-themes"; |
import { useTheme } from "next-themes"; |
||||||
|
|
||||||
export type FuncProps = { |
export type FuncProps = { |
||||||
init: () => THREE.Vector3[]; |
init: () => THREE.Vector3[]; |
||||||
update: (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => void; |
update: (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => void; |
||||||
}; |
}; |
||||||
|
|
||||||
export type ParticleProps = { |
export type ParticleProps = { |
||||||
max?: number; |
max?: number; |
||||||
size?: number; |
size?: number; |
||||||
color?: string; |
color?: string; |
||||||
darkcolor?: string; |
darkcolor?: string; |
||||||
opacity?: number; |
opacity?: number; |
||||||
}; |
}; |
||||||
|
|
||||||
export type CameraProps = { |
export type CameraProps = { |
||||||
pos?: THREE.Vector3; |
pos?: THREE.Vector3; |
||||||
lookAt?: THREE.Vector3; |
lookAt?: THREE.Vector3; |
||||||
rotation?: THREE.Vector3; |
rotation?: THREE.Vector3; |
||||||
}; |
}; |
||||||
|
|
||||||
export type CurveProps = { |
export type CurveProps = { |
||||||
func: FuncProps; |
func: FuncProps; |
||||||
cam?: CameraProps; |
cam?: CameraProps; |
||||||
particles?: ParticleProps; |
particles?: ParticleProps; |
||||||
}; |
}; |
||||||
|
|
||||||
export const FuncRenderer = ({ |
export const FuncRenderer = ({ |
||||||
func, |
func, |
||||||
cam = { |
cam = { |
||||||
pos: new THREE.Vector3(0, 0, 0), |
pos: new THREE.Vector3(0, 0, 0), |
||||||
lookAt: new THREE.Vector3(0, 0, 0), |
lookAt: new THREE.Vector3(0, 0, 0), |
||||||
rotation: new THREE.Vector3(0, 0, 0), |
rotation: new THREE.Vector3(0, 0, 0), |
||||||
}, |
}, |
||||||
particles = { |
particles = { |
||||||
max: 10000, |
max: 10000, |
||||||
size: 1, |
size: 1, |
||||||
color: "#000", |
color: "#000", |
||||||
darkcolor: "#fff", |
darkcolor: "#fff", |
||||||
opacity: 1, |
opacity: 1, |
||||||
}, |
}, |
||||||
}: CurveProps) => { |
}: CurveProps) => { |
||||||
const groupRef = useRef<THREE.Group>(null); |
const groupRef = useRef<THREE.Group>(null); |
||||||
const { gl, camera } = useThree(); |
const { gl, camera } = useThree(); |
||||||
const { theme } = useTheme(); |
const { theme } = useTheme(); |
||||||
|
|
||||||
const isDarkMode = theme === "dark"; |
const isDarkMode = theme === "dark"; |
||||||
|
|
||||||
useEffect(() => { |
useEffect(() => { |
||||||
if (cam.pos) camera.position.copy(cam.pos); |
if (cam.pos) camera.position.copy(cam.pos); |
||||||
if (cam.lookAt) camera.lookAt(cam.lookAt); |
if (cam.lookAt) camera.lookAt(cam.lookAt); |
||||||
if (cam.rotation) { |
if (cam.rotation) { |
||||||
camera.rotateX(cam.rotation.x); |
camera.rotateX(cam.rotation.x); |
||||||
camera.rotateY(cam.rotation.y); |
camera.rotateY(cam.rotation.y); |
||||||
camera.rotateZ(cam.rotation.z); |
camera.rotateZ(cam.rotation.z); |
||||||
} |
} |
||||||
|
|
||||||
// Initialize and set up the points on mount
|
// Initialize and set up the points on mount
|
||||||
if (groupRef.current) { |
if (groupRef.current) { |
||||||
const arrayCurve = func.init(); |
const arrayCurve = func.init(); |
||||||
const romCurve = new THREE.CatmullRomCurve3(arrayCurve); |
const romCurve = new THREE.CatmullRomCurve3(arrayCurve); |
||||||
const points = romCurve.getPoints(particles.max); |
const points = romCurve.getPoints(particles.max); |
||||||
const geometry = new THREE.BufferGeometry().setFromPoints(points); |
const geometry = new THREE.BufferGeometry().setFromPoints(points); |
||||||
|
|
||||||
const pcMat = new THREE.PointsMaterial({ |
const pcMat = new THREE.PointsMaterial({ |
||||||
size: particles.size, |
size: particles.size, |
||||||
color: isDarkMode ? particles.darkcolor : particles.color, |
color: isDarkMode ? particles.darkcolor : particles.color, |
||||||
opacity: particles.opacity, |
opacity: particles.opacity, |
||||||
transparent: true, |
transparent: true, |
||||||
}); |
}); |
||||||
// pcMat.blending = THREE.AdditiveBlending;
|
// pcMat.blending = THREE.AdditiveBlending;
|
||||||
|
|
||||||
const pc = new THREE.Points(geometry, pcMat); |
const pc = new THREE.Points(geometry, pcMat); |
||||||
groupRef.current.add(pc); |
groupRef.current.add(pc); |
||||||
} |
} |
||||||
|
|
||||||
return () => { |
return () => { |
||||||
// Clean up any resources if needed
|
// Clean up any resources if needed
|
||||||
}; |
}; |
||||||
}, [cam, func, particles, camera, isDarkMode]); |
}, [cam, func, particles, camera, isDarkMode]); |
||||||
|
|
||||||
useFrame(() => { |
useFrame(() => { |
||||||
gl.setPixelRatio(window.devicePixelRatio); |
gl.setPixelRatio(window.devicePixelRatio); |
||||||
if (groupRef.current && groupRef.current.children.length > 0) { |
if (groupRef.current && groupRef.current.children.length > 0) { |
||||||
const pc = groupRef.current.children[0] as THREE.Points; |
const pc = groupRef.current.children[0] as THREE.Points; |
||||||
if (pc.geometry) { |
if (pc.geometry) { |
||||||
func.update(pc, groupRef.current); |
func.update(pc, groupRef.current); |
||||||
} |
} |
||||||
} |
} |
||||||
}); |
}); |
||||||
|
|
||||||
return <group ref={groupRef} />; |
return <group ref={groupRef} />; |
||||||
}; |
}; |
||||||
|
|
||||||
const Renderer: React.FC< |
const Renderer: React.FC< |
||||||
ComponentPropsWithRef<typeof FuncRenderer> & { |
ComponentPropsWithRef<typeof FuncRenderer> & { |
||||||
cam?: CameraProps; |
cam?: CameraProps; |
||||||
} |
} |
||||||
> = ({ cam = { pos: new THREE.Vector3(0, 0, 0) }, ...props }) => { |
> = ({ cam = { pos: new THREE.Vector3(0, 0, 0) }, ...props }) => { |
||||||
return ( |
return ( |
||||||
<Canvas gl={{ alpha: true }} className="transform"> |
<Canvas gl={{ alpha: true }} className="transform"> |
||||||
<pointLight position={[0, 0, 0]} color="#fff" /> |
<pointLight position={[0, 0, 0]} color="#fff" /> |
||||||
<perspectiveCamera position={cam.pos} /> |
<perspectiveCamera position={cam.pos} /> |
||||||
<FuncRenderer cam={cam} {...props} /> |
<FuncRenderer cam={cam} {...props} /> |
||||||
</Canvas> |
</Canvas> |
||||||
); |
); |
||||||
}; |
}; |
||||||
|
|
||||||
export default Renderer; |
export default Renderer; |
||||||
|
Loading…
Reference in new issue