As long as I can remember, I have always been attracted by Space. But then i heard about programming...
Hy there! Today we will create mars planet using three.js and react-three-fiber.
What are three.js and react-three-fiber?
This tutorial is for those who already know the basics of three.js. There i won't go into details since there are already so many introductory guides. Today i want to focus on practise.
But in brief:
- three.js β it's JavaScript library for creating 3D graphics.
- react-three-fiber β is a React renderer for three.js on the web and react-native.
Here we go!
First! The structure of our files in this guide:
Now let's dwell on the details. In our project, we need to create three main components:
- Sphere β this will be the planet Mars
-
SkyBox β this is our space, we will use
CubeTextureLoader()
to create it. For this component we need to get 6 images for the background of each side of the cube. - CameraControls β very important component. This will give us the ability to rotate and scale our Sphere (Mars) as we want.
Sphere creating
Let's start with the Sphere component:
import React, { useRef } from "react";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { useFrame, useLoader } from "react-three-fiber";
const Sphere = () => {
const planet = useRef();
const { nodes } = useLoader(GLTFLoader, "models/mars.glb");
useFrame(() => (planet.current.rotation.y += 0.0002));
return (
<mesh
ref={planet}
visible
position={[0, 0, 0]}
// Adding data from mars.glb to the geometry and material of the sphere
geometry={nodes.Cube008.geometry}
material={nodes.Cube008.material}
/>
);
};
export default Sphere;
```
We are using a ready-made gltf 3D file that creates the geometry and material for our sphere. We can get it from [the official NASA website](https://solarsystem.nasa.gov/resources/2372/mars-3d-model/). To work with the gltf file we use the [GLTFLoader](https://threejs.org/docs/#examples/en/loaders/GLTFLoader) from three.js and the `useLoader()` hook from react-three-fiber. Also we use the `useFrame()` hook that add rotation for our planet.
### **SkyBox creating**
Notice how SkyBox returns null this is because we will not be creating any new objects with this component in our scene. Instead, we will use it as a controller to set a property in our scene, as we will see in the next step when we load and apply the skybox textures.
```javascript
import { useThree } from "react-three-fiber";
import { CubeTextureLoader } from "three";
// Loads the skybox texture and applies it to the scene.
const SkyBox = () => {
const { scene } = useThree();
const loader = new CubeTextureLoader();
// The CubeTextureLoader load method takes an array of urls representing all 6 sides of the cube.
const texture = loader.load([
"/images/front.jpg",
"/images/back.jpg",
"/images/top.jpg",
"/images/bottom.jpg",
"/images/left.jpg",
"/images/right.jpg",
]);
// Set the scene background property to the resulting texture.
scene.background = texture;
return null;
};
export default SkyBox;
```
To start we need to get a reference of our Three.JS scene and for that we use `useThree()` hook. Then we create an instance of the CubeTextureLoader and then call the load method with an array containing the six URLs of your images. This will return a CubeTexture. The CubeTexture we assign to the global `scene.background` which we get a reference to with `useThree()`, and that's it our skybox is finished.
### **Skybox Textures**
Also important to talk about Skybox textures creating. For this purpose i was using [Spacescape](http://alexcpeterson.com/spacescape/) program. This is a simple space landscape generator. You can use it or create assets in Photoshop or something.
### **Camera Controls**
And the last thing about camera control. Here we are using [OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls), which allows the camera to rotate around the target.
```javascript
import React, { useRef } from "react";
import { extend, useThree, useFrame } from "react-three-fiber";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
extend({ OrbitControls });
const CameraControls = () => {
const {
camera,
gl: { domElement },
} = useThree();
// Ref to the controls, so that we can update them on every frame with useFrame
const controls = useRef();
camera.position.z = 999;
useFrame(() => controls.current.update());
return (
<orbitControls
ref={controls}
args={[camera, domElement]}
autoRotate={false}
enableZoom={false}
/>
);
};
export default CameraControls;
```
### **Finish**
Now we can use all created components in to the App component:
```javascript
import React, { Suspense } from "react";
import { Canvas } from "react-three-fiber";
import "./styles.css";
import { CameraControls, Sphere, SkyBox } from "./components";
const App = () => {
return (
<>
<Canvas className="canvas">
<CameraControls />
<directionalLight intensity={1} />
<ambientLight intensity={0.6} />
<Suspense fallback="loading">
<Sphere />
</Suspense>
<SkyBox />
</Canvas>
</>
);
};
export default App;
```
And also add Styles in to styles.css:
```css
* {
box-sizing: border-box;
}
html,
body,
#root {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
```
**Well that's all. Thanks for reading =)**
Top comments (1)
i love this...