Spaces:
Running
Running
get faces
Browse files- src/components/consts.tsx +13 -4
- src/components/cube-piece.tsx +13 -14
- src/components/rotation-controller.ts +38 -1
- src/components/ui-controls.tsx +3 -1
src/components/consts.tsx
CHANGED
|
@@ -1,12 +1,21 @@
|
|
| 1 |
-
export type FacingDirection = 'front' | 'back' | '
|
| 2 |
|
| 3 |
export type RotationDirection = 'clockwise' | 'counter-clockwise';
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
export const Rotations: Record<FacingDirection, [number, number, number]> = {
|
| 6 |
front: [0, 0, 0],
|
| 7 |
back: [0, Math.PI, 0],
|
| 8 |
-
left: [0, -Math.PI / 2, 0],
|
| 9 |
right: [0, Math.PI / 2, 0],
|
|
|
|
| 10 |
top: [-Math.PI / 2, 0, 0],
|
| 11 |
bottom: [Math.PI / 2, 0, 0],
|
| 12 |
};
|
|
@@ -19,12 +28,12 @@ export type RotationStep = {
|
|
| 19 |
export const Actions: Array<RotationStep> = [
|
| 20 |
{ faceDirection: 'front', direction: 'clockwise' },
|
| 21 |
{ faceDirection: 'front', direction: 'counter-clockwise' },
|
|
|
|
|
|
|
| 22 |
{ faceDirection: 'right', direction: 'clockwise' },
|
| 23 |
{ faceDirection: 'right', direction: 'counter-clockwise' },
|
| 24 |
{ faceDirection: 'left', direction: 'clockwise' },
|
| 25 |
{ faceDirection: 'left', direction: 'counter-clockwise' },
|
| 26 |
-
{ faceDirection: 'back', direction: 'clockwise' },
|
| 27 |
-
{ faceDirection: 'back', direction: 'counter-clockwise' },
|
| 28 |
{ faceDirection: 'top', direction: 'clockwise' },
|
| 29 |
{ faceDirection: 'top', direction: 'counter-clockwise' },
|
| 30 |
{ faceDirection: 'bottom', direction: 'clockwise' },
|
|
|
|
| 1 |
+
export type FacingDirection = 'front' | 'back' | 'right' | 'left' | 'top' | 'bottom';
|
| 2 |
|
| 3 |
export type RotationDirection = 'clockwise' | 'counter-clockwise';
|
| 4 |
|
| 5 |
+
export const CubeColors: Record<FacingDirection, string> = {
|
| 6 |
+
front: '#ff0000', // Red
|
| 7 |
+
back: '#ff00ff', // Purple
|
| 8 |
+
right: '#0000ff', // Blue
|
| 9 |
+
left: '#00ff00', // Green
|
| 10 |
+
top: '#ffff00', // Yellow
|
| 11 |
+
bottom: '#ffffff', // White
|
| 12 |
+
};
|
| 13 |
+
|
| 14 |
export const Rotations: Record<FacingDirection, [number, number, number]> = {
|
| 15 |
front: [0, 0, 0],
|
| 16 |
back: [0, Math.PI, 0],
|
|
|
|
| 17 |
right: [0, Math.PI / 2, 0],
|
| 18 |
+
left: [0, -Math.PI / 2, 0],
|
| 19 |
top: [-Math.PI / 2, 0, 0],
|
| 20 |
bottom: [Math.PI / 2, 0, 0],
|
| 21 |
};
|
|
|
|
| 28 |
export const Actions: Array<RotationStep> = [
|
| 29 |
{ faceDirection: 'front', direction: 'clockwise' },
|
| 30 |
{ faceDirection: 'front', direction: 'counter-clockwise' },
|
| 31 |
+
{ faceDirection: 'back', direction: 'clockwise' },
|
| 32 |
+
{ faceDirection: 'back', direction: 'counter-clockwise' },
|
| 33 |
{ faceDirection: 'right', direction: 'clockwise' },
|
| 34 |
{ faceDirection: 'right', direction: 'counter-clockwise' },
|
| 35 |
{ faceDirection: 'left', direction: 'clockwise' },
|
| 36 |
{ faceDirection: 'left', direction: 'counter-clockwise' },
|
|
|
|
|
|
|
| 37 |
{ faceDirection: 'top', direction: 'clockwise' },
|
| 38 |
{ faceDirection: 'top', direction: 'counter-clockwise' },
|
| 39 |
{ faceDirection: 'bottom', direction: 'clockwise' },
|
src/components/cube-piece.tsx
CHANGED
|
@@ -4,19 +4,9 @@ import { RoundedBox } from '@react-three/drei';
|
|
| 4 |
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
| 5 |
import { Mesh } from 'three';
|
| 6 |
|
| 7 |
-
import { FacingDirection, Rotations } from './consts';
|
| 8 |
import { rotationController } from './rotation-controller';
|
| 9 |
|
| 10 |
-
// Standard Rubik's cube colors
|
| 11 |
-
const CUBE_COLORS = {
|
| 12 |
-
front: '#ff0000', // Red
|
| 13 |
-
back: '#ff00ff', // Purple
|
| 14 |
-
left: '#00ff00', // Green
|
| 15 |
-
right: '#0000ff', // Blue
|
| 16 |
-
top: '#ffff00', // Yellow
|
| 17 |
-
bottom: '#ffffff', // White
|
| 18 |
-
};
|
| 19 |
-
|
| 20 |
export type CubePieceRef = {
|
| 21 |
resetPosition: () => void;
|
| 22 |
};
|
|
@@ -54,8 +44,8 @@ export const CubePiece = forwardRef<CubePieceRef, CubePieceProps>(({ roughness,
|
|
| 54 |
const positions: Record<FacingDirection, [number, number, number]> = {
|
| 55 |
front: [0, 0, 0.48],
|
| 56 |
back: [0, 0, -0.48],
|
| 57 |
-
left: [-0.48, 0, 0],
|
| 58 |
right: [0.48, 0, 0],
|
|
|
|
| 59 |
top: [0, 0.48, 0],
|
| 60 |
bottom: [0, -0.48, 0],
|
| 61 |
};
|
|
@@ -68,9 +58,18 @@ export const CubePiece = forwardRef<CubePieceRef, CubePieceProps>(({ roughness,
|
|
| 68 |
|
| 69 |
{Object.entries(visibleFaces).map(([face, isVisible]) => {
|
| 70 |
if (!isVisible) return null;
|
| 71 |
-
const color =
|
| 72 |
return (
|
| 73 |
-
<mesh
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
<planeGeometry args={[0.8, 0.8]} />
|
| 75 |
<meshStandardMaterial color={color} metalness={1} roughness={roughness} />
|
| 76 |
</mesh>
|
|
|
|
| 4 |
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
| 5 |
import { Mesh } from 'three';
|
| 6 |
|
| 7 |
+
import { CubeColors, FacingDirection, Rotations } from './consts';
|
| 8 |
import { rotationController } from './rotation-controller';
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
export type CubePieceRef = {
|
| 11 |
resetPosition: () => void;
|
| 12 |
};
|
|
|
|
| 44 |
const positions: Record<FacingDirection, [number, number, number]> = {
|
| 45 |
front: [0, 0, 0.48],
|
| 46 |
back: [0, 0, -0.48],
|
|
|
|
| 47 |
right: [0.48, 0, 0],
|
| 48 |
+
left: [-0.48, 0, 0],
|
| 49 |
top: [0, 0.48, 0],
|
| 50 |
bottom: [0, -0.48, 0],
|
| 51 |
};
|
|
|
|
| 58 |
|
| 59 |
{Object.entries(visibleFaces).map(([face, isVisible]) => {
|
| 60 |
if (!isVisible) return null;
|
| 61 |
+
const color = CubeColors[face as keyof typeof CubeColors];
|
| 62 |
return (
|
| 63 |
+
<mesh
|
| 64 |
+
key={face}
|
| 65 |
+
position={positions[face as FacingDirection]}
|
| 66 |
+
rotation={Rotations[face as FacingDirection]}
|
| 67 |
+
userData={{
|
| 68 |
+
isFace: true,
|
| 69 |
+
faceDirection: face,
|
| 70 |
+
faceColor: color,
|
| 71 |
+
}}
|
| 72 |
+
>
|
| 73 |
<planeGeometry args={[0.8, 0.8]} />
|
| 74 |
<meshStandardMaterial color={color} metalness={1} roughness={roughness} />
|
| 75 |
</mesh>
|
src/components/rotation-controller.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import { Group, Mesh } from 'three';
|
| 2 |
|
| 3 |
import { FacingDirection, RotationStep } from './consts';
|
| 4 |
|
|
@@ -58,6 +58,38 @@ export class RotationController {
|
|
| 58 |
return false;
|
| 59 |
}
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
static getInstance() {
|
| 62 |
if (!RotationController.instance) {
|
| 63 |
RotationController.instance = new RotationController();
|
|
@@ -102,6 +134,11 @@ export class RotationController {
|
|
| 102 |
}
|
| 103 |
}
|
| 104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
setCubeSpeed(cubeSpeed: number) {
|
| 106 |
this.cubeSpeed = cubeSpeed;
|
| 107 |
}
|
|
|
|
| 1 |
+
import { Group, Mesh, Vector3 } from 'three';
|
| 2 |
|
| 3 |
import { FacingDirection, RotationStep } from './consts';
|
| 4 |
|
|
|
|
| 58 |
return false;
|
| 59 |
}
|
| 60 |
|
| 61 |
+
private getCubeFace(mesh: Mesh, faceDirection: FacingDirection) {
|
| 62 |
+
const faces = mesh.children.filter((child) => child.userData.isFace);
|
| 63 |
+
let axis: 'x' | 'y' | 'z' = 'x';
|
| 64 |
+
switch (faceDirection) {
|
| 65 |
+
case 'front':
|
| 66 |
+
case 'back':
|
| 67 |
+
axis = 'z';
|
| 68 |
+
break;
|
| 69 |
+
case 'right':
|
| 70 |
+
case 'left':
|
| 71 |
+
axis = 'x';
|
| 72 |
+
break;
|
| 73 |
+
case 'top':
|
| 74 |
+
case 'bottom':
|
| 75 |
+
axis = 'y';
|
| 76 |
+
break;
|
| 77 |
+
}
|
| 78 |
+
let maxFace: Mesh | null = null;
|
| 79 |
+
let maxValue = -Infinity;
|
| 80 |
+
for (const face of faces) {
|
| 81 |
+
const worldPosition = new Vector3();
|
| 82 |
+
face.getWorldPosition(worldPosition);
|
| 83 |
+
const axisValue = Math.abs(worldPosition[axis]);
|
| 84 |
+
if (axisValue > maxValue) {
|
| 85 |
+
maxValue = axisValue;
|
| 86 |
+
maxFace = face as Mesh;
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
if (!maxFace) return null;
|
| 90 |
+
return maxFace;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
static getInstance() {
|
| 94 |
if (!RotationController.instance) {
|
| 95 |
RotationController.instance = new RotationController();
|
|
|
|
| 134 |
}
|
| 135 |
}
|
| 136 |
|
| 137 |
+
getFaces(faceDirection: FacingDirection) {
|
| 138 |
+
const cubes = this.getCubes(faceDirection);
|
| 139 |
+
return cubes.map((cube) => this.getCubeFace(cube, faceDirection));
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
setCubeSpeed(cubeSpeed: number) {
|
| 143 |
this.cubeSpeed = cubeSpeed;
|
| 144 |
}
|
src/components/ui-controls.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import { useState } from 'react';
|
|
| 6 |
import { useControlContext } from '@/contexts/control-context';
|
| 7 |
|
| 8 |
import { Actions } from './consts';
|
|
|
|
| 9 |
|
| 10 |
export const UIControls = () => {
|
| 11 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
|
@@ -30,7 +31,8 @@ export const UIControls = () => {
|
|
| 30 |
};
|
| 31 |
|
| 32 |
const showState = () => {
|
| 33 |
-
|
|
|
|
| 34 |
};
|
| 35 |
|
| 36 |
const solve = () => {
|
|
|
|
| 6 |
import { useControlContext } from '@/contexts/control-context';
|
| 7 |
|
| 8 |
import { Actions } from './consts';
|
| 9 |
+
import { rotationController } from './rotation-controller';
|
| 10 |
|
| 11 |
export const UIControls = () => {
|
| 12 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
|
|
|
| 31 |
};
|
| 32 |
|
| 33 |
const showState = () => {
|
| 34 |
+
const faces = rotationController.getFaces('front');
|
| 35 |
+
console.log(faces);
|
| 36 |
};
|
| 37 |
|
| 38 |
const solve = () => {
|