React Native de Threejs nasıl kullanılır?

Alper Bayram
5 min read4 days ago

--

Three.js, WebGL teknolojisini kullanarak 3D nesneler ve animasyonlar oluşturmak ve oluşturulmuş üç boyutlu modelleri de kullanmak için oluşturulmuş bir JavaScript kütüphanesidir. Bu yazıda react nativede kullanarak mobil uygulamalarda 3D cisimler ve objelerin nasıl oluşturulacağından bahsedeceğim.

Uygulamalı olarak expo ile yapacağım.

Expo kuruyorum aşağıdaki kodu kopyalayınız.

npx create-expo-app -t expo-template-blank-typescript expo-threejs
cd expo-threejs

React Native de kullanmak için aşağıdaki paketleri kurmamız gerekiyor.

npx expo install three @react-three/fiber@8.13.6 expo-gl expo-three expo-file-system

tüm paket kurulumlarını tamaladıktan sonra expo uygulamasını başlatalım.

npm start

uygulamayı başlattıktan qr ios telefonumdan okutarak devam ediyorum. ios simulatör uyumlu olmadığı için çalışmayacaktır. android de simulatörde deneyebilirsiniz.

şimdi yavaş yavaş uygulamamıza başlayalım App.tsx içine giderek Canvas ekliyorum canvas tüm sahnemizin bulunacağı kök dizin olarak belirtmemiz gerekiyor. şimdilik bir simit şeklinde bir cisim ekleyelim.<torusGeometry /> ekliyorum bunun gibi bir çok geometrik cisim ekleyebilirsiniz hazır olarak ve gösterebiliriz bunlardan bazıları BoxGeometry ,CapsuleGeometry ,CircleGeometry ,ConeGeometry ,CylinderGeometry daha fazlası için bu linki ziyaret edebilirsiniz. link

import { Canvas } from "@react-three/fiber";

export default function App() {
return (
<Canvas>
<mesh>
<torusGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</Canvas>
);
}
simit

şimdi eklediğimiz cisim istediğimiz renkte görüntülemiyoruz bunun sebebi ışık eklememiş olmamız şimdi ekleyeceğimiz ışık türü gölge oluşturmayan ve eşit bir şekilde aydınlatama yapan bir tür <ambientLight /> ekledikten sonra istediğimiz rengi elde etmiş olduk. Daha fazla ışık türünü denemek için threejs dökümantasyonunu inceleyebilirsiniz.

import { Canvas } from "@react-three/fiber";

export default function App() {
return (
<Canvas>
<mesh>
<ambientLight />
<torusGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</Canvas>
);
}
simit2

şimdi bu cisimi tıklandığında x ve y ekseninde hareket ettiren animasyonu ekleyelim.

import { Canvas, useFrame } from "@react-three/fiber";
import { useRef, useState } from "react";

function Torus(props) {
const [active, setActive] = useState(false);
const mesh = useRef();
useFrame((state, delta) => {
if (active) {
mesh.current.rotation.x += delta;
mesh.current.rotation.y += delta;
}
});

return (
<mesh {...props} ref={mesh} onClick={(event) => setActive(!active)}>
<torusGeometry args={[1, 0.4, 16, 100]} />
<meshStandardMaterial
color={active ? "orange" : "green"}
metalness={0.7}
roughness={0.2}
/>
</mesh>
);
}

export default function App() {
return (
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Torus />
</Canvas>
);
}

useFrame fonksiyonu, her animasyon karesinde yapılacak işlemleri tanımlamak için kullanılır. Bu fonksiyonla nesnelerin pozisyonunu, rotasyonunu, ölçeğini ve diğer özelliklerini dinamik olarak değiştirebilirsiniz.

React Native de orbitcontrols nasıl eklenir?

Bu cismi elle haraket ettirmek için three.js fonksiyonu olan orbit controller ekleyelim.

Bunu için bu paketi kullanıyorum.

npm install r3f-native-orbitcontrols --legacy-peer-deps

paketi kurduktan sonra app.tsx son hali aşağıdaki gibi

import { View } from "react-native";
import { Canvas, useFrame } from "@react-three/fiber";
import { useRef, useState } from "react";
import useControls from "r3f-native-orbitcontrols";
import { PerspectiveCamera } from "three";

function Torus(props) {
const [active, setActive] = useState(false);
const mesh = useRef();
useFrame((state, delta) => {
if (active) {
mesh.current.rotation.x += delta;
mesh.current.rotation.y += delta;
}
});

return (
<mesh {...props} ref={mesh} onClick={(event) => setActive(!active)}>
<torusGeometry args={[1, 0.4, 16, 100]} />
<meshStandardMaterial
color={active ? "orange" : "green"}
metalness={0.7}
roughness={0.2}
/>
</mesh>
);
}

export default function App() {
const [OrbitControls, events] = useControls();
const camera = new PerspectiveCamera();

return (
<View style={{ flex: 1 }} {...events}>
<Canvas camera={camera}>
<OrbitControls minZoom={5} maxZoom={10} enablePan={false} />
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Torus />
</Canvas>
</View>
);
}

artık cisimi haraket ettirebiliyoruz.

React Native de obj nasıl eklenir?

şimdi sıra bir objeyi sahnemize eklemeye ve hareket ettirmeye obj olarak basketbol topu obj, mtl ve textura dosyalarını buldum ve projeme ekledim.

npx expo customize metro.config.js

metro.config.js oluşturduktan sonra aşağıdaki gibi güncelleyelim.

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

config.resolver = {
...config.resolver,
sourceExts: ["js", "jsx", "json", "ts", "tsx", "cjs"],
assetExts: ["glb", "gltf", "mtl", "obj", "png", "jpg"],
};

module.exports = config;

projeyi başlatan başlatalım.

npm start --reset-cache

Ardından gerekli loaderları import ettikten sonra Ball function <Suspense> içinde <Canvas> içerisine ekledim. mtl dosyamı obj load ettikten sonra textureları yüklüyorum.

import { View } from "react-native";
import { Canvas, useLoader } from "@react-three/fiber";
import { useRef, Suspense, useLayoutEffect } from "react";
import useControls from "r3f-native-orbitcontrols";
import { PerspectiveCamera } from "three";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { TextureLoader } from "expo-three";

function Ball() {
const [base, normal, rough] = useLoader(TextureLoader, [
require("./assets/ball/basket/ball_ball_BaseColor.png"),
require("./assets/ball/basket/ball_ball_Normal.png"),
require("./assets/ball/basket/ball_ball_Roughness.png"),
]);

const material = useLoader(MTLLoader, require("./assets/ball/basket.mtl"));

const obj = useLoader(
OBJLoader,
require("./assets/ball/basket.obj"),
(loader) => {
material.preload();
loader.setMaterials(material);
}
);

const mesh = useRef();

useLayoutEffect(() => {
obj.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material.map = base;
child.material.normalMap = normal;
child.material.roughnessMap = rough;
}
});
}, [obj]);

return (
<mesh ref={mesh} rotation={[0, 0, 0]}>
<primitive object={obj} scale={10} />
</mesh>
);
}

export default function App() {
const [OrbitControls, events] = useControls();
const camera = new PerspectiveCamera();

return (
<View style={{ flex: 1 }} {...events}>
<Canvas camera={camera}>
<OrbitControls minZoom={5} maxZoom={10} enablePan={false} />
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Suspense fallback={null}>
<Ball />
</Suspense>
</Canvas>
</View>
);
}

elde ettiğimiz objenin görüntüsü aşağıdaki gibidir.

react native de threejs kullanımından bahsettiğim yazımda bu şekildeydi tüm kodları github reposundan erişebilirsiniz. okuduğunuz için teşekkürler. iyi çalışmalar.

--

--