I came across this http://3doc.i3dconverter.com Tool. The free version sufficed for experimentation reasons - it was able to import the base C3 file in an C3 folder and convert it to an .obj format, where I then used an Online converter to conver the .obj to gbl/gltf format.
Note: The free version of the tool will remove every 5th polygon from the exported version, for demo purposes it didn't matter but keep that in mind.
Once in the .glb/gltf format, I used this npx package to convert the gltf file straight into a Js/Jsx component that can be imported into the react app and rendered inside a react-three fiber canvas:
Code: Select all
import React, { useRef, useState, Suspense } from "react";
import { Canvas, useFrame, useThree, extend } from "react-three-fiber";
import * as THREE from "three";
import './App.css'
import FemaleTro from './FemaleTro';
import Piggie from './Piggie';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// Extend will make OrbitControls available as a JSX element called orbitControls for us to use.
extend({ OrbitControls });
const Box = (props) => {
// This reference will give us direct access to the mesh
const mesh = useRef();
// Set up state for the hovered and active state
const [active, setActive] = useState(false);
// Rotate mesh every frame, this is outside of React without overhead
useFrame(() => {
mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
});
return (
<mesh
{...props}
ref={mesh}
scale={active ? [2, 2, 2] : [1.5, 1.5, 1.5]}
onClick={(e) => setActive(!active)}
>
<boxBufferGeometry args={[1, 1, 1]} />
<meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}>
</meshBasicMaterial>
</mesh>
);
}
const CameraControls = () => {
// Get a reference to the Three.js Camera, and the canvas html element.
// We need these to setup the OrbitControls class.
// https://threejs.org/docs/#examples/en/controls/OrbitControls
const {
camera,
gl: { domElement },
} = useThree();
// Ref to the controls, so that we can update them on every frame using useFrame
const controls = useRef();
useFrame((state) => controls.current.update());
return (
<orbitControls
ref={controls}
args={[camera, domElement]}
enableZoom={true}
maxAzimuthAngle={Math.PI / 23}
maxPolarAngle={Math.PI}
minAzimuthAngle={-Math.PI / 4}
minPolarAngle={0}
/>
);
};
const App = () => {
return (
<Canvas>
<CameraControls />
<Suspense fallback={null}>
<ambientLight intensity={0.5} />
<spotLight position={[10, 10, 10]} angle={5.15} penumbra={1} />
<pointLight position={[0, 0, 0]} />
<FemaleTro />
</Suspense>
</Canvas>
);
}
export default App;
Code: Select all
"dependencies": {
"@react-three/drei": "^4.0.1",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"react-three-fiber": "^5.3.22",
"three": "^0.127.0",
},
https://imgur.com/g1Pef4S
It's by no means perfect but it was something I managed to put together in short amount of time to see what was possible.
Happy to hear of more efficient ways of doing the conversion, or if there are even better processes in place for rendering this stuff in browser. It was actually this project that set me down the path of looking at different sources and trying to learn more about the conquer private server eco system. I hope to pick it back up and create a proper garment/item/npc viewer in browser for more robust webpages/guides.
Hope this proof of concept/demo helps if anyone had similar ideas in mind!