opinions/best practices with rotating objects

Hello!
First time here on the forum. Like many of you I am learning, and would love some eyes from more expereinced folks!

I am making a logo of sorts as a first stab at this. The logo is two rotating letters produced with textGeometry which i want to sort of blend together.

I have a parent mesh with the two letters inside, they are placed on top of eachother, the second child is rotated 180° ahead of the other, and they take turns alternating visibility so it looks like a “G” rotates, vanishes and a “P” takes its place to do the same.

The issue is this doesn’t look fabulous the way I’ve done it. The objects seem to have immperfect center points, so the rotation looks sloppy, and same for the visibility swap.

this is what i’ve got:

Index

import { useRef, Suspense } from "react";
import { Canvas, useFrame, useLoader } from "@react-three/fiber";
import TextMesh from "./TextMesh";
import { FontLoader } from "three/examples/jsm/Addons.js";

function Logo() {
  const font = useLoader(FontLoader, "/font.data");
  return (
    <Suspense fallback={<h1>loading...</h1>}>
      <Canvas dpr={[1, 2]} fallback={<div>Sorry no WebGL supported!</div>}>
        <ambientLight intensity={0.3} />
        {/* <spotLight position={[2, 2, 2]} angle={0.15} penumbra={0.5} intensity={1} shadow-mapSize={2048} castShadow={true} /> */}
        <pointLight castShadow position={[0, 0, -2]} />
        <spotLight castShadow position={[0, 0, 2]} penumbra={1} />

        <TextMesh position={[0, 0, 0]} character={"G"} font={font} />
        <TextMesh position={[0, 0, 0]} character={"P"} font={font} rotationOffset={Math.PI} />
      </Canvas>
    </Suspense>
  );
}

export default Logo;

TextMesh

import { useRef, useState } from "react";
import { TextGeometry } from "three/examples/jsm/Addons.js";
import { useFrame, extend } from "@react-three/fiber";

extend({ TextGeometry });

function TextMesh({ character, position, font, rotationOffset = 0 }: { character: string; position: number[]; font: any; rotationOffset: number }) {
  const textMesh = useRef();
  const [isVisible, setIsVisible] = useState(rotationOffset === 0); // First object visible, second object hidden
  const rotationTracker = useRef(0); // To track cumulative rotation
  let additionalRoation = Math.PI / 0.52;

  useFrame((state, delta) => {
    const currentRotation = textMesh.current.rotation.y + delta;

    // Update rotation
    textMesh.current.rotation.y = currentRotation;

    // Check for 180 degree rotation (Math.PI)
    rotationTracker.current += delta;
    if (rotationTracker.current >= Math.PI) {
      setIsVisible((prev) => !prev); // Toggle visibility every 180 degrees with boolean swap
      rotationTracker.current = 0; // Reset tracker
    }
  });
  return (
    <mesh castShadow receiveShadow ref={textMesh} position={position} rotation={[0, rotationOffset + additionalRoation, 0]} visible={isVisible}>
      {/* <mesh castShadow receiveShadow ref={textMesh} position={position} rotation={rotationOffset}> */}
      <textGeometry args={[character, { font: font, size: 1, depth: 0.2 }]} />
      <meshStandardMaterial attach="material" color="orange" />
    </mesh>
  );
}

export default TextMesh;

edit: sorry realized I included the index file twice, also added an additional roation so the letters “swap visibility” when the viewer is looking at them from “the side”