main
Elias Almqvist 8 months ago
parent ae1a514854
commit ac4b24e4a2
No known key found for this signature in database
GPG Key ID: E31A99CE3E75A158
  1. 164
      src/components/3d/curves/thing.ts
  2. 68
      src/components/3d/renderedsection.tsx
  3. 228
      src/components/3d/renderer.tsx
  4. 41
      src/components/ui/card.tsx

@ -1,82 +1,82 @@
"use client";
import * as THREE from "three";
import { CurveProps } from "../renderer";
const maxParticles = 20000;
const startScatter = 0.1;
const init = () => {
var arrayCurve = [];
var x = 0.01,
y = 0.01,
z = 0.01;
var a = 0.9;
var b = 3.4;
var f = 9.9;
var g = 1;
var t = 0.001;
for (var i = 0; i < maxParticles; i++) {
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;
z = z - t * z + t * b * x * y + t * x * z;
arrayCurve.push(
new THREE.Vector3(x, y, z).multiplyScalar(
1 - startScatter / 2 + Math.random() * startScatter,
),
);
}
return arrayCurve;
};
const update = (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => {
//Varying the points on each frame
// step += 0.01;
var geometry = pc.geometry;
var a = 0.9; //+ Math.random() * .2;
var b = 3.4; //+ Math.random() * .1;
var f = 9.9; //+ Math.random() * .2;
var g = 1; //+ Math.random() * .1;
var t = 0.001;
var positions = geometry.attributes.position;
const numPoints = positions.array.length / 3;
for (let i = 0; i < numPoints; i++) {
let x = positions.getX(i),
y = positions.getY(i),
z = positions.getZ(i);
positions.setXYZ(
i,
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,
z - t * z + t * b * x * y + t * x * z,
);
}
positions.needsUpdate = true;
// TODO: remove
// group.rotation.x += 0.0005;
// group.rotation.y += 0.001;
// group.rotation.z -= 0.0005;
};
// INFO: Curve definition
const ThingCurve = {
func: { init: init, update: update },
cam: {
pos: new THREE.Vector3(0, 0, 18).multiplyScalar(1.7),
rotation: new THREE.Vector3(0, 0, 180),
},
particles: {
max: maxParticles,
size: 0.07,
color: "#888",
darkcolor: "#444",
opacity: 0.4,
}, // 87a
};
export default ThingCurve;
"use client";
import * as THREE from "three";
import { CurveProps } from "../renderer";
const maxParticles = 20000;
const startScatter = 0.1;
const init = () => {
var arrayCurve = [];
var x = 0.01,
y = 0.01,
z = 0.01;
var a = 0.9;
var b = 3.4;
var f = 9.9;
var g = 1;
var t = 0.001;
for (var i = 0; i < maxParticles; i++) {
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;
z = z - t * z + t * b * x * y + t * x * z;
arrayCurve.push(
new THREE.Vector3(x, y, z).multiplyScalar(
1 - startScatter / 2 + Math.random() * startScatter,
),
);
}
return arrayCurve;
};
const update = (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => {
//Varying the points on each frame
// step += 0.01;
var geometry = pc.geometry;
var a = 0.9; //+ Math.random() * .2;
var b = 3.4; //+ Math.random() * .1;
var f = 9.9; //+ Math.random() * .2;
var g = 1; //+ Math.random() * .1;
var t = 0.001;
var positions = geometry.attributes.position;
const numPoints = positions.array.length / 3;
for (let i = 0; i < numPoints; i++) {
let x = positions.getX(i),
y = positions.getY(i),
z = positions.getZ(i);
positions.setXYZ(
i,
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,
z - t * z + t * b * x * y + t * x * z,
);
}
positions.needsUpdate = true;
// TODO: remove
// group.rotation.x += 0.0005;
// group.rotation.y += 0.001;
// group.rotation.z -= 0.0005;
};
// INFO: Curve definition
const ThingCurve = {
func: { init: init, update: update },
cam: {
pos: new THREE.Vector3(0, 0, 18).multiplyScalar(1.7),
rotation: new THREE.Vector3(0, 0, 180),
},
particles: {
max: maxParticles,
size: 0.07,
color: "#888",
darkcolor: "#444",
opacity: 0.4,
}, // 87a
};
export default ThingCurve;

@ -1,34 +1,34 @@
"use client";
import React, { ReactNode, HTMLProps } from "react";
import Renderer, { CurveProps } from "@/components/3d/renderer";
import { cn } from "@/lib/utils";
const RenderedSection: React.FC<
HTMLProps<HTMLElement> & {
children?: ReactNode;
evenly?: boolean;
curve: CurveProps;
curveClassname?: string;
}
> = ({
children,
className,
curveClassname,
evenly = false,
curve,
...props
}) => {
return (
<div className="flex w-full h-full flex-col items-center align-middle relative">
<div className={cn("absolute", curveClassname)}>
<Renderer {...curve} />
</div>
<section className={cn("relative", className)} {...props}>
{children}
</section>
</div>
);
};
export default RenderedSection;
"use client";
import React, { ReactNode, HTMLProps } from "react";
import Renderer, { CurveProps } from "@/components/3d/renderer";
import { cn } from "@/lib/utils";
const RenderedSection: React.FC<
HTMLProps<HTMLElement> & {
children?: ReactNode;
evenly?: boolean;
curve: CurveProps;
curveClassname?: string;
}
> = ({
children,
className,
curveClassname,
evenly = false,
curve,
...props
}) => {
return (
<div className="flex w-full h-full flex-col items-center align-middle relative">
<div className={cn("absolute", curveClassname)}>
<Renderer {...curve} />
</div>
<section className={cn("relative", className)} {...props}>
{children}
</section>
</div>
);
};
export default RenderedSection;

@ -1,114 +1,114 @@
"use client";
import * as THREE from "three";
import React, { ComponentPropsWithRef, useEffect, useRef } from "react";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { useTheme } from "next-themes";
export type FuncProps = {
init: () => THREE.Vector3[];
update: (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => void;
};
export type ParticleProps = {
max?: number;
size?: number;
color?: string;
darkcolor?: string;
opacity?: number;
};
export type CameraProps = {
pos?: THREE.Vector3;
lookAt?: THREE.Vector3;
rotation?: THREE.Vector3;
};
export type CurveProps = {
func: FuncProps;
cam?: CameraProps;
particles?: ParticleProps;
};
export const FuncRenderer = ({
func,
cam = {
pos: new THREE.Vector3(0, 0, 0),
lookAt: new THREE.Vector3(0, 0, 0),
rotation: new THREE.Vector3(0, 0, 0),
},
particles = {
max: 10000,
size: 1,
color: "#000",
darkcolor: "#fff",
opacity: 1,
},
}: CurveProps) => {
const groupRef = useRef<THREE.Group>(null);
const { gl, camera } = useThree();
const { theme } = useTheme();
const isDarkMode = theme === "dark";
useEffect(() => {
if (cam.pos) camera.position.copy(cam.pos);
if (cam.lookAt) camera.lookAt(cam.lookAt);
if (cam.rotation) {
camera.rotateX(cam.rotation.x);
camera.rotateY(cam.rotation.y);
camera.rotateZ(cam.rotation.z);
}
// Initialize and set up the points on mount
if (groupRef.current) {
const arrayCurve = func.init();
const romCurve = new THREE.CatmullRomCurve3(arrayCurve);
const points = romCurve.getPoints(particles.max);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const pcMat = new THREE.PointsMaterial({
size: particles.size,
color: isDarkMode ? particles.darkcolor : particles.color,
opacity: particles.opacity,
transparent: true,
});
// pcMat.blending = THREE.AdditiveBlending;
const pc = new THREE.Points(geometry, pcMat);
groupRef.current.add(pc);
}
return () => {
// Clean up any resources if needed
};
}, [cam, func, particles, camera, isDarkMode]);
useFrame(() => {
gl.setPixelRatio(window.devicePixelRatio);
if (groupRef.current && groupRef.current.children.length > 0) {
const pc = groupRef.current.children[0] as THREE.Points;
if (pc.geometry) {
func.update(pc, groupRef.current);
}
}
});
return <group ref={groupRef} />;
};
const Renderer: React.FC<
ComponentPropsWithRef<typeof FuncRenderer> & {
cam?: CameraProps;
}
> = ({ cam = { pos: new THREE.Vector3(0, 0, 0) }, ...props }) => {
return (
<Canvas gl={{ alpha: true }} className="transform">
<pointLight position={[0, 0, 0]} color="#fff" />
<perspectiveCamera position={cam.pos} />
<FuncRenderer cam={cam} {...props} />
</Canvas>
);
};
export default Renderer;
"use client";
import * as THREE from "three";
import React, { ComponentPropsWithRef, useEffect, useRef } from "react";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { useTheme } from "next-themes";
export type FuncProps = {
init: () => THREE.Vector3[];
update: (pc: THREE.Points<THREE.BufferGeometry>, group: THREE.Group) => void;
};
export type ParticleProps = {
max?: number;
size?: number;
color?: string;
darkcolor?: string;
opacity?: number;
};
export type CameraProps = {
pos?: THREE.Vector3;
lookAt?: THREE.Vector3;
rotation?: THREE.Vector3;
};
export type CurveProps = {
func: FuncProps;
cam?: CameraProps;
particles?: ParticleProps;
};
export const FuncRenderer = ({
func,
cam = {
pos: new THREE.Vector3(0, 0, 0),
lookAt: new THREE.Vector3(0, 0, 0),
rotation: new THREE.Vector3(0, 0, 0),
},
particles = {
max: 10000,
size: 1,
color: "#000",
darkcolor: "#fff",
opacity: 1,
},
}: CurveProps) => {
const groupRef = useRef<THREE.Group>(null);
const { gl, camera } = useThree();
const { theme } = useTheme();
const isDarkMode = theme === "dark";
useEffect(() => {
if (cam.pos) camera.position.copy(cam.pos);
if (cam.lookAt) camera.lookAt(cam.lookAt);
if (cam.rotation) {
camera.rotateX(cam.rotation.x);
camera.rotateY(cam.rotation.y);
camera.rotateZ(cam.rotation.z);
}
// Initialize and set up the points on mount
if (groupRef.current) {
const arrayCurve = func.init();
const romCurve = new THREE.CatmullRomCurve3(arrayCurve);
const points = romCurve.getPoints(particles.max);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const pcMat = new THREE.PointsMaterial({
size: particles.size,
color: isDarkMode ? particles.darkcolor : particles.color,
opacity: particles.opacity,
transparent: true,
});
// pcMat.blending = THREE.AdditiveBlending;
const pc = new THREE.Points(geometry, pcMat);
groupRef.current.add(pc);
}
return () => {
// Clean up any resources if needed
};
}, [cam, func, particles, camera, isDarkMode]);
useFrame(() => {
gl.setPixelRatio(window.devicePixelRatio);
if (groupRef.current && groupRef.current.children.length > 0) {
const pc = groupRef.current.children[0] as THREE.Points;
if (pc.geometry) {
func.update(pc, groupRef.current);
}
}
});
return <group ref={groupRef} />;
};
const Renderer: React.FC<
ComponentPropsWithRef<typeof FuncRenderer> & {
cam?: CameraProps;
}
> = ({ cam = { pos: new THREE.Vector3(0, 0, 0) }, ...props }) => {
return (
<Canvas gl={{ alpha: true }} className="transform">
<pointLight position={[0, 0, 0]} color="#fff" />
<perspectiveCamera position={cam.pos} />
<FuncRenderer cam={cam} {...props} />
</Canvas>
);
};
export default Renderer;

@ -1,6 +1,6 @@
import * as React from "react"
import * as React from "react";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
const Card = React.forwardRef<
HTMLDivElement,
@ -10,12 +10,12 @@ const Card = React.forwardRef<
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className
className,
)}
{...props}
/>
))
Card.displayName = "Card"
));
Card.displayName = "Card";
const CardHeader = React.forwardRef<
HTMLDivElement,
@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"
));
CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef<
HTMLParagraphElement,
@ -37,12 +37,12 @@ const CardTitle = React.forwardRef<
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className
className,
)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"
));
CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef<
HTMLParagraphElement,
@ -53,16 +53,16 @@ const CardDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"
));
CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"
));
CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef<
HTMLDivElement,
@ -73,7 +73,14 @@ const CardFooter = React.forwardRef<
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"
));
CardFooter.displayName = "CardFooter";
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};

Loading…
Cancel
Save