W - I -React Native 3D
React Native
React Native es un framework JavaScript para crear aplicaciones reales nativas para iOS y Android, basado en la librearía de JavaScript React para la creación de componentes visuales
Expo vs Cli
Las aplicaciones React Native CLI requieren macOS para crear aplicaciones iOS, lo que significa que los usuarios de Windows no pueden desarrollar aplicaciones iOS sin algunas soluciones provisionales.
Expo evita por completo esta limitación al ofrecer un servicio alojado llamado EAS Build para crear binarios de aplicaciones para sus proyectos Expo y React Native. Esto abre un mercado completamente nuevo para los usuarios de Windows y Linux.
También automatiza y facilita el proceso de creación al proporcionar valores predeterminados configurados para proyectos Expo y React Native, así como también maneja las credenciales de firma de su aplicación, proporcionando la forma más rápida de implementar en las tiendas de aplicaciones. Puede enviar aplicaciones directamente desde su CLI usando EAS Enviar.
Requisitos
- Node
- Expo
- React native
- Cuenta en expo
Uso de 3D
Uso de opengl
Para el uso de open gl, a diferencia de web que es webgl, necesitamos un visor que muestre objectos en 3D, en react native existe la herramienta la cual es gl-view
https://docs.expo.dev/versions/latest/sdk/gl-view/
La cual nos ayuda a mostrar objetos en 3d, lo cual esta limitado a figuras geometricas, y no a modelos
Uso de modelos
Para el uso de modelos, se usan una herramienta que puede ayudarnos las cuales son threejs, pero no funciona todos sus puntos de manera efectiva.
Para poder agregarlo se puede con expo-three
https://github.com/expo/expo-three
de esta manera puedes agregar modelos
Advertencia
Algunas paginas o videos te diran que ocupes react three fiber
https://docs.pmnd.rs/react-three-fiber/getting-started/introduction
si se puede ocupar hasta un punto, es mejor ocuparlo como lo marca expo-three, dado que en desarrollo funciona correctamente, porque es un servidor, pero en producción las apk no funcionan de la misma manera, dado que ya no es un servidor, y se rompe cuando llega al modelo, asi que tal vez funcione si se manden a llamadar desde algun space los modelos y texturas, pero de manera local no funciona.
Carga de modelos
Cuando se cargan modelos, movil, se puede ocupar cualquier tipo solo que es muy dificil hacer que funcione, con glb, gltf y fbx, es recomendable usar obj
Configurar metro
Primeramente necesitas modificar lo que es metro, que es indicar como leer otro tipo de extensiones mas información en https://docs.expo.dev/guides/customizing-metro/
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname)
config.resolver.assetExts.push("obj", "mtl", "xpng", "xjpg");
module.exports = config;
Expo assets
Para cargar algunos assets se necesita expo assets, para generar un ulr de donde se encuentra tu assets como file//archivo.
https://docs.expo.dev/versions/latest/sdk/asset/
Codigo three
Para acceder a glview, llamas al componente react, y en onContextCreate agregar un method, no acepta clases solo methods
<GLView
style={{ height: "100%", width: "100%" }}
onContextCreate={onContextCreate}
/>
Codigo de three, a diferencia de web, que se usa el windows, con las propiedades clientHeight y clientWidth, en gl, viene drawingBufferWidth y drawingBufferHeight
// importaciones
import ExpoTHREE, { Renderer, TextureLoader } from "expo-three";
const onContextCreate = async (gl) => {
// Scene
const scene = new Scene();
// Camara
const camera = new PerspectiveCamera(
75,
gl.drawingBufferWidth / gl.drawingBufferHeight,
0.1,
1000
);
gl.canvas = {
width: gl.drawingBufferWidth,
height: gl.drawingBufferHeight,
};
camera.position.z = 2;
const ambientLight = new AmbientLight(0xffffff);
ambientLight.intensity = 1;
scene.add(ambientLight);
// renderer
const renderer = new Renderer({ gl });
renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
// -- codigo que sigue --
// - va al final
const render = () => {
requestAnimationFrame(render);
renderer.render(scene, camera);
gl.endFrameEXP();
};
// call render
render();
}
Cargar modelo
// react native lo pide los assets con require
let model = require("../../assets/model/model.obj");
// necesitamos el localUri que es file//assets, donde se encuentra guardado
const [{ localUri: localObj }] = await Asset.loadAsync(model);
// textura, tiene que tener xpng, mas adelante se explica, aqui se usa la
// textureLoader de expo-three no de three directamente
let textures = require("../../assets/texture/texture.xpng");
const texture1 = new TextureLoader().load(textures);
// se pasa por un mesh que quieras, la mayoria usa meshPong
texture1.magFilter = NearestFilter;
texture1.minFilter = NearestFilter;
material = new MeshPhongMaterial({
map: texture1,
flatShading: true,
emissiveIntensity: 0,
shininess: 0,
reflectivity: 0,
});
// viene de three
const loader = new OBJLoader();
loader.load(
localObj,
function (object) {
childFuntion(object, material, 0);
objectModel = object;
actionActiveButton(true);
scene.add(object);
},
function (xhr) {},
function (error) {}
);
Advertencia de codigo
Para poder cargar los modelos obj, consiste en varias cosas, como obj, mtl y una textura.
- obj => es importante
- mtl => no es tan relevante, cuidado con el mismo nombre
- texture => tiene que ser en png y luego cambiar la extension manualmente a xpng
Para poder cargar los modelos obj, consiste en varias cosas, como obj, mtl y una textura.
Extension xpng
La extension para cargar imagenes regulamente es png, pero cuando la guarda en la apk, la guarda de manera diferente entonces al final la apk, le el nombre de la imagen y no la ruta, de la imagen como file//assets, eso se debe a que android no guarda la ruta, para que lo haga, se necesita poner xpng que es una forma de decirle que lo guarde en el drawer que es el cache del apk, para mas información aqui https://github.com/expo/expo-three/issues/185#issuecomment-732161813
Cargar modelos glb, gltf, fbx
Es algo dificil porque sucede lo mismo, pero existe la manera de hacerlo, eso ya no lo pude probar, pero esta persona fue quien resolvio las dudas de xpng y el porque falla algunos modelos
https://github.com/expo/expo-three/issues/151#issuecomment-904532776
Mover un modelo sobre la pantalla
Es algo dificil porque no lo lograron como tal, dado que se sobre pone los gestos de pantalla contra los gestos de mover modelos, asi que logras mover el modelo, perderas la funcionalidad de dar tap, pero puedes poner los gestos de pantalla de expo gesture y con eso podrias aplicar el movimiento, pero atraves de orbit controls no se puede
Cuidado con nombres repetidos
Cuando se compila android pasa los assets a un metodo el cual, no pregunta el tipo solo lo guarda, entonces cuando son extensiones poco comunes como mtl, obj, android no entienden la diferencia por la extension entonces verifica el nombre, si encuentra texture.png y textura.jpg, el comprende que son dos imagenes, pero estas teniendo duplicado de assest y falla, entonces cuando te pasen el obj viene con un nombre que es mtl, y al compilar genera el duplicado. https://stackoverflow.com/questions/53239705/react-native-error-duplicate-resources-android
yarn
usarlo, porque en algunos puntos, cuando instalas algo yarn se encarga de hacer la instalación de dependencias, y npm no.
Link de proyectos de guia
https://github.com/kyaroru/RNExpoThree
https://github.com/aaronbesson/Space-Walker-3D
https://github.com/EvanBacon/Expo-Crossy-Road
El futuro del 3d nativo
Flutter
React native
Muchos dicen que si se puede, usando open gl, pero no dicen que a un tiene muchas deficiencias y poco control a parte de poner un modelo y ya.
Librerias
https://github.com/BonnierNews/react-native-3d-model-view
https://github.com/rastapasta/react-native-gl-model-view
Existen muchas librerias que facilitan ese problema, pero sucede que son librerias pasadas entonces al usar react native nuevo, ya no es compatible y el pasado tiene muchos problemas de compatibilidad como el mas importante usar react native link, en las nuevas versiones ya no existe, y en las pasadas versiones react native tiene varios bugs.
Important: You only need to do this step if you're using React Native 0.59 or lower. Since v0.60, linking happens automatically.