Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 10x 284x 142x 142x 142x 142x 142x 142x 142x 142x 284x 142x 142x 284x | /**
* Foot3D component with anatomically accurate foot geometry
*
* Renders detailed 3D foot with proper dimensions for martial arts stances
* and kicks. Supports left/right feet with Korean skin tone coloring.
*
* Implements anatomically correct foot proportions:
* - Length: ~26-29cm (varies by archetype)
* - Width: ~10cm at widest point
* - Height: ~8cm at ankle
*
* @module components/three/Foot3D
* @category 3D Components
* @korean 발3D컴포넌트
*/
import React, { useMemo } from "react";
import { KOREAN_COLORS } from "../../../../types/constants";
/**
* Props for Foot3D component
*
* @public
* @korean 발3D속성
*/
export interface Foot3DProps {
/**
* Foot side (left or right)
* @korean 발쪽
*/
readonly side: "left" | "right";
/**
* Base skin color
* @korean 피부색
*/
readonly skinColor?: number;
/**
* Scale multiplier (based on archetype physical attributes)
* @korean 크기배율
*/
readonly scale?: number;
/**
* Whether foot is highlighted (e.g., during kicks)
* @korean 표시여부
*/
readonly isHighlighted?: boolean;
}
/**
* Foot3D Component
*
* Complete foot geometry with anatomically correct dimensions suitable
* for Korean martial arts stance visualization and kick animations.
*
* Design notes:
* - Main foot body is box-shaped with rounded edges
* - Toe area is slightly elevated and separated
* - Heel is wider than toe area for stability
* - Dimensions scale with archetype (Amsalja: smaller, Jojik: larger)
*
* @example
* ```tsx
* <Foot3D
* side="right"
* skinColor={0xffdbac}
* scale={1.0}
* isHighlighted={false}
* />
* ```
*
* @korean 발3D컴포넌트
*/
export const Foot3D: React.FC<Foot3DProps> = ({
side,
skinColor = 0xffdbac,
scale = 1.0,
isHighlighted = false,
}) => {
// Anatomically correct foot dimensions for average male (180cm height)
// These scale with archetype physical attributes
const footDimensions = useMemo(() => {
// Average male foot: 26-29cm length, ~10cm width, ~8cm height
const footLength = 0.26 * scale; // 26cm base length
const footWidth = 0.1 * scale; // 10cm width
const footHeight = 0.08 * scale; // 8cm height at ankle
// Toe area dimensions (front 30% of foot)
const toeLength = footLength * 0.3;
const toeWidth = footWidth * 0.9; // Slightly narrower than heel
const toeHeight = footHeight * 0.6; // Lower profile
// Heel area dimensions (back 70% of foot)
const heelLength = footLength * 0.7;
return {
footLength,
footWidth,
footHeight,
toeLength,
toeWidth,
toeHeight,
heelLength,
};
}, [scale]);
// Foot color (highlight during kicks with brighter color)
const footColor = useMemo(() => {
Iif (isHighlighted) {
return KOREAN_COLORS.ACCENT_GOLD;
}
return skinColor;
}, [isHighlighted, skinColor]);
return (
<group name={`foot-3d-${side}`}>
{/* Main heel/midfoot body */}
<mesh
position={[0, -footDimensions.footHeight / 2, 0]}
castShadow
receiveShadow
name={`foot-heel-${side}`}
>
<boxGeometry
args={[
footDimensions.footWidth,
footDimensions.footHeight,
footDimensions.heelLength,
]}
/>
<meshStandardMaterial
color={footColor}
metalness={0.1}
roughness={0.9}
/>
</mesh>
{/* Toe area (slightly raised and forward) */}
<mesh
position={[
0,
-footDimensions.footHeight / 2 + footDimensions.toeHeight * 0.2,
footDimensions.heelLength / 2 + footDimensions.toeLength / 2,
]}
castShadow
receiveShadow
name={`foot-toes-${side}`}
>
<boxGeometry
args={[
footDimensions.toeWidth,
footDimensions.toeHeight,
footDimensions.toeLength,
]}
/>
<meshStandardMaterial
color={footColor}
metalness={0.1}
roughness={0.9}
/>
</mesh>
{/* Ankle connection point indicator (small sphere for visual continuity) */}
<mesh
position={[0, 0, -footDimensions.heelLength * 0.3]}
castShadow
name={`foot-ankle-${side}`}
>
<sphereGeometry args={[footDimensions.footHeight * 0.4, 8, 8]} />
<meshStandardMaterial
color={footColor}
metalness={0.1}
roughness={0.9}
/>
</mesh>
</group>
);
};
export default Foot3D;
|