Skip to content

Commit

Permalink
修复每个字体的字体基线高度不同导致的贴图偏移问题
Browse files Browse the repository at this point in the history
  • Loading branch information
boybook committed Dec 23, 2024
1 parent dcc17d9 commit d364f1d
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 22 deletions.
3 changes: 2 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { materialGradientLightBlue, materialGradientMediumYellow } from "./prese
import { MessageProvider } from "./contexts/MessageContext";
import { useLanguage } from "./language.tsx";
import SceneAndCameraSettingsPanel from "./components/SceneAndCameraSettingsPanel.tsx";
import { builtinFontsMap } from "./utils/fonts.ts";
import { builtinFontsMap, builtinFontsTextureYOffset } from "./utils/fonts.ts";

const { Sider, Content } = Layout;
const { Panel } = Collapse;
Expand Down Expand Up @@ -267,6 +267,7 @@ const App: React.FC = () => {
cameraOptions={cameraOptions}
texts={texts}
fontUrl={fontsMap[selectedFont]}
globalTextureYOffset={builtinFontsTextureYOffset[selectedFont] ?? 0}
/>
{/* 添加截图按钮 */}
<Flex gap={"small"} style={{ position: "absolute", top: 20, right: 20, zIndex: 1 }}>
Expand Down
9 changes: 6 additions & 3 deletions src/components/Text3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface Text3DProps {
content: string;
opts: TextOptions;
font: Font;
globalTextureYOffset: number;
position: [number, number, number];
rotation: [number, number, number];
}
Expand All @@ -20,6 +21,7 @@ const Text3D = forwardRef<THREE.Group, Text3DProps>(({
content,
opts,
font,
globalTextureYOffset,
position,
rotation
}, ref) => {
Expand Down Expand Up @@ -48,9 +50,10 @@ const Text3D = forwardRef<THREE.Group, Text3DProps>(({
const textMaterial = useMemo(() =>
createCubeMaterial(
opts.materials,
boundingBox
boundingBox,
globalTextureYOffset
),
[opts.materials, boundingBox]
[opts.materials, boundingBox, globalTextureYOffset]
);

const height = boundingBox.max.y - boundingBox.min.y;
Expand All @@ -73,7 +76,7 @@ const Text3D = forwardRef<THREE.Group, Text3DProps>(({
}, [content, opts.size, opts.depth, font, opts.letterSpacing, opts.spacingWidth, opts.outlineWidth]);

const outlineMaterial = useMemo(() =>
createMeshBasicMaterialFromOption(opts.materials.outline, false, [1, 1], [1, 1], { side: THREE.BackSide }),
createMeshBasicMaterialFromOption(opts.materials.outline, false, [1, 1], [1, 1], [0, 0], { side: THREE.BackSide }),
[opts.materials]
);

Expand Down
4 changes: 3 additions & 1 deletion src/components/ThreeCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface ThreeCanvasProps {
cameraOptions: CameraOptions;
texts: Text3DData[];
fontUrl: string;
globalTextureYOffset: number;
}

const CameraController: React.FC<{ fov: number }> = ({ fov }) => {
Expand All @@ -40,7 +41,7 @@ interface ScreenshotProps {
}

const ThreeCanvas = forwardRef<ThreeCanvasHandle, ThreeCanvasProps>((props, ref) => {
const { texts, cameraOptions, fontUrl } = props;
const { texts, cameraOptions, fontUrl, globalTextureYOffset } = props;
const orbitRef = useRef<OrbitControlsImpl>(null);
const threeSceneRef = useRef<ThreeSceneHandle>(null);
const messageApi = useMessage();
Expand Down Expand Up @@ -299,6 +300,7 @@ const ThreeCanvas = forwardRef<ThreeCanvasHandle, ThreeCanvasProps>((props, ref)
ref={threeSceneRef}
texts={texts}
fontUrl={fontUrl}
globalTextureYOffset={globalTextureYOffset}
/>
<OrbitControls ref={orbitRef} enableDamping={false} dampingFactor={0} />
</Canvas>
Expand Down
4 changes: 3 additions & 1 deletion src/components/ThreeScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import customFontsStore from "../utils/localForageInstance.ts";
interface ThreeSceneProps {
texts: Text3DData[];
fontUrl: string;
globalTextureYOffset: number;
}

const cachedFonts : {[id: string]: Font} = {}
Expand All @@ -21,7 +22,7 @@ export interface ThreeSceneHandle {
groupRef: React.RefObject<THREE.Group>;
}

const ThreeScene = forwardRef<ThreeSceneHandle, ThreeSceneProps>(({ texts, fontUrl }, ref) => {
const ThreeScene = forwardRef<ThreeSceneHandle, ThreeSceneProps>(({ texts, fontUrl, globalTextureYOffset }, ref) => {

const groupRef = useRef<THREE.Group>(null);

Expand Down Expand Up @@ -123,6 +124,7 @@ const ThreeScene = forwardRef<ThreeSceneHandle, ThreeSceneProps>(({ texts, fontU
key={index}
content={text.content}
opts={text.opts}
globalTextureYOffset={globalTextureYOffset}
font={font}
position={[0, text.opts.y, 0]}
rotation={[text.opts.rotY * (Math.PI / 180), 0, 0]}
Expand Down
14 changes: 14 additions & 0 deletions src/language.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ export const languageConfig: Readonly<LanguageConfig> = {
message: "Restore to the last scene? ({count} texts)",
apply: "Apply",
delete: "Delete"
},
customFont: {
namePlaceHolder: "Custom Font",
upload: "Upload",
nameEmpty: "Please input the font name first",
success: "Font added successfully",
failed: "Font adding failed (please check the console for more details)",
}
},
ja_JP: {
Expand Down Expand Up @@ -196,6 +203,13 @@ export const languageConfig: Readonly<LanguageConfig> = {
message: "前回のシーンに戻りますか?({count}行)",
apply: "適用",
delete: "削除"
},
customFont: {
namePlaceHolder: "カスタムフォント",
upload: "アップロード",
nameEmpty: "フォント名を入力してください",
success: "フォントが追加されました",
failed: "フォントの追加に失敗しました(詳細はコンソールを確認してください)"
}
},
};
Expand Down
8 changes: 4 additions & 4 deletions src/presetMaterials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ export const materialCherry: TextMaterials = {
repeatX: 1,
repeatY: 2,
offsetX: 0,
offsetY: 0.1,
offsetY: 0,
} as TextMaterialImageOption,
back: {
mode: "color",
Expand Down Expand Up @@ -393,7 +393,7 @@ export const materialGrass: TextMaterials = {
repeatX: 0.5,
repeatY: 1,
offsetX: 0,
offsetY: 0.1,
offsetY: 0,
} as TextMaterialImageOption,
back: {
mode: "color",
Expand Down Expand Up @@ -440,7 +440,7 @@ export const materialAtmosphere: TextMaterials = {
repeatX: 0.4545454545,
repeatY: 1,
offsetX: 0,
offsetY: 0.1
offsetY: 0
} as TextMaterialImageOption,
back: {
mode: "gradient",
Expand Down Expand Up @@ -486,7 +486,7 @@ export const materialWinter: TextMaterials = {
repeatX: 0.5,
repeatY: 1,
offsetX: 0,
offsetY: 0.1,
offsetY: 0,
} as TextMaterialImageOption,
back: {
mode: "color",
Expand Down
9 changes: 8 additions & 1 deletion src/utils/fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@ export const builtinFontsMap: { [name: string]: string } = {
"Minecraft Ten": "font/Minecraft_Ten_Regular.json",
"Fusion Pixel 8px": "font/Fusion_Pixel_8px_Proportional_zh_hans_Regular.json",
"Fusion Pixel 10px": "font/Fusion_Pixel_10px_Proportional_zh_hans_Regular.json",
};
};

export const builtinFontsTextureYOffset: { [name: string]: number } = {
"REEJI Taiko Magic": 0.1,
"汉仪力量黑(简)": 0.18,
"Fusion Pixel 8px": 0.15,
"Fusion Pixel 10px": 0.115,
}
25 changes: 14 additions & 11 deletions src/utils/textMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ export const createMeshStandardMaterialFromOption = (
export const createMeshBasicMaterialFromOption = (
option: TextMaterialOption,
reverseGradient: boolean = false,
extraRepeat: [number, number] = [1, 1],
extraOffset: [number, number] = [1, 1],
repeatScale: [number, number] = [1, 1],
offsetScale: [number, number] = [1, 1],
extraOffset: [number, number] = [0, 0],
extra: { [key: string]: any } = {}
) : THREE.MeshBasicMaterial => {
if (option.mode == 'color') {
Expand All @@ -77,16 +78,16 @@ export const createMeshBasicMaterialFromOption = (
return new THREE.MeshBasicMaterial({ map: createGradientTexture(
reverseGradient ? option.colorGradualEnd : option.colorGradualStart,
reverseGradient ? option.colorGradualStart: option.colorGradualEnd,
option.repeat * extraRepeat[1],
option.offset * extraOffset[1]
option.repeat * repeatScale[1],
option.offset * offsetScale[1] + extraOffset[1]
), ...extra });
} else if (option.mode === 'image') {
const texture = new THREE.TextureLoader().load(option.image);
// 根据需求设置 wrap 模式与 repeat、offset 等
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(option.repeatX * extraRepeat[0], (reverseGradient ? -option.repeatY : option.repeatY) * extraRepeat[1]);
texture.offset.set(option.offsetX * extraOffset[0], (reverseGradient ? 1 - option.offsetY : option.offsetY) * extraOffset[1]);
texture.repeat.set(option.repeatX * repeatScale[0], (reverseGradient ? -option.repeatY : option.repeatY) * repeatScale[1]);
texture.offset.set(option.offsetX * offsetScale[0] + extraOffset[0], (reverseGradient ? 1 - option.offsetY : option.offsetY) * offsetScale[1] + extraOffset[1]);

texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
Expand All @@ -106,18 +107,20 @@ export const createMeshBasicMaterialFromOption = (
// 创建立方体贴图材质
export const createCubeMaterial = (
materials: TextMaterials,
boundingBox: THREE.Box3
boundingBox: THREE.Box3,
globalTextureYOffset: number
): THREE.Material[] => {
const repeatFront = [1 / (boundingBox.max.y - boundingBox.min.y), 1 / (boundingBox.max.y - boundingBox.min.y)] as [number, number];
const repeatSide = [1 / (boundingBox.max.y - boundingBox.min.y), 1 / (boundingBox.max.z - boundingBox.min.z)] as [number, number];
//const offsetSide = [(boundingBox.max.z - boundingBox.min.z) / 2, (boundingBox.max.z - boundingBox.min.z) / 2] as [number, number];
const offsetSide = [1, 1] as [number, number]; // TODO: 修正偏移量
const extraOffset: [number, number] = [0, globalTextureYOffset];
return [
createMeshBasicMaterialFromOption(materials.right, true, repeatSide, offsetSide), // 右面
createMeshBasicMaterialFromOption(materials.left, true, repeatSide, offsetSide), // 左面
createMeshBasicMaterialFromOption(materials.right, true, repeatSide, offsetSide, extraOffset), // 右面
createMeshBasicMaterialFromOption(materials.left, true, repeatSide, offsetSide, extraOffset), // 左面
createMeshBasicMaterialFromOption(materials.up, true, repeatSide, offsetSide), // 上面
createMeshBasicMaterialFromOption(materials.down, true, repeatSide, offsetSide), // 下面
createMeshBasicMaterialFromOption(materials.front, false, repeatFront), // 前面
createMeshBasicMaterialFromOption(materials.back, false, repeatFront), // 后面
createMeshBasicMaterialFromOption(materials.front, false, repeatFront, [1, 1], extraOffset), // 前面
createMeshBasicMaterialFromOption(materials.back, false, repeatFront, [1, 1], extraOffset), // 后面
];
};

0 comments on commit d364f1d

Please sign in to comment.