React 3d Model Viewer

React 3d Model Viewer
Project: 3D Model Viewer
Author: llifeboa
Edit Online: View on CodePen
License: MIT

This React component helps you to create a responsive 3D model viewer. It initializes a canvas element with the dimensions of the window. Loads a 3D mesh file from a URL and parses it as a JSON object. Defines a Mesh class representing the 3D mesh, with methods to rotate and render it on the HTML canvas element. Creates a new Mesh object using the loaded mesh file and applies an initial rotation to it. Sets up a rendering loop that repeatedly rotates and renders the Mesh object on the canvas using the requestAnimationFrame function.

The canvas is filled with a black color before rendering each frame. When the window is resized, the canvas dimensions are updated accordingly. You can set the custom fill color according to your needs.

How to Create a 3D Model Viewer using ReactJS

First of all, create the HTML canvas element that will be used to draw the 3D modal.

<canvas></canvas>

Set a background color for the canvas element using CSS. You can set a custom color according to your requirements.

canvas{
	background-color: #111;
}

Finally, add the following JavaScript function to activate the 3D modal viewer. You just need to pass the link of the 3D file inside the mesh_request.open() function to view it in the viewer.

const canvas = document.querySelector('canvas');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let width = canvas.offsetWidth; // Width of the scene
let height = canvas.offsetHeight; // Height of the scene

const ctx = canvas.getContext('2d');

let centerX = width / 2;
let centerY = height / 2;

window.addEventListener('resize', ()=>{
	console.log('resized');
	canvas.width = window.innerWidth;
	canvas.height = window.innerHeight;
	width = canvas.offsetWidth; // Width of the scene
	height = canvas.offsetHeight; // Height of the scene
	centerX = width / 2;
	centerY = height / 2;
});


const mesh_request = new XMLHttpRequest();
mesh_request.open('GET' ,'https://raw.githubusercontent.com/llifeboa/OBJtoJSON/master/wolf.json', false);
mesh_request.send();

console.log(JSON.parse(mesh_request.responseText));

class Mesh{
	constructor(mesh)
	{
		this.vertices = mesh.vertices;
		this.triangles =  mesh.triangles;
		this.center = mesh.center;
		this.scale = 2000;
		this.projection = 5;
	}
	
	rotateY(theta){
		this.vertices = this.vertices.map( vertice =>{
			let x = vertice[0], y = vertice[1], z = vertice[2];
			return [
				 Math.cos(theta) * x - Math.sin(theta) * z,
					y,
				 Math.sin(theta) * x + Math.cos(theta) * z
			];
		}
		);
	}
	rotateX(theta){
		this.vertices = this.vertices.map( vertice =>{
			let x = vertice[0], y = vertice[1], z = vertice[2];
			return [
				 x,
					Math.cos(theta) * y - Math.sin(theta) * z,
				 Math.sin(theta) * y + Math.cos(theta) * z
			];
		}
		);
		
	}
	
	rotateZ(theta){
		this.vertices = this.vertices.map( vertice =>{
			let x = vertice[0], y = vertice[1], z = vertice[2];
			return [
				 Math.cos(theta) * x - Math.sin(theta) * y,
					Math.cos(theta) * x + Math.sin(theta) * y,
				 z
			];
		}
		);
		
	}
	
	render(){
		for (let triangle of this.triangles){
			let v1 = this.vertices[triangle[0]];
			let v2 = this.vertices[triangle[1]];
			let v3 = this.vertices[triangle[2]];
			let zB = (-(this.vertices[triangle[0]][2] + this.vertices[triangle[1]][2] + this.vertices[triangle[2]][2]) / 3 + 1) / 2;
			ctx.beginPath()
			
			ctx.strokeStyle = `rgba(255, 255, 255, ${zB}`;
			//
				
			//
			ctx.moveTo((v1[0] / (v1[2] + this.projection)) * this.scale + centerX, (v1[1] / (v1[2] + this.projection)) * this.scale + centerY);
			ctx.lineTo((v2[0] / (v2[2] + this.projection)) * this.scale + centerX, (v2[1] / (v2[2] + this.projection)) * this.scale + centerY);
			ctx.lineTo((v3[0] / (v3[2] + this.projection)) * this.scale + centerX, (v3[1] / (v3[2] + this.projection)) * this.scale + centerY);
			ctx.lineTo((v1[0] / (v1[2] + this.projection)) * this.scale + centerX, (v1[1] / (v1[2] + this.projection)) * this.scale + centerY);
			ctx.closePath();
			ctx.stroke();
		};
	}
	
}

let a = new Mesh(JSON.parse(mesh_request.responseText));

a.rotateX(Math.PI);
//a.rotateZ(Math.PI/4);

	(function main() {
		ctx.rect(0, 0, width, height);
		ctx.fillStyle ='#111';
		ctx.fill();
		a.rotateY(0.01);
		a.render();
		window.requestAnimationFrame(main);
	})();

That’s all! hopefully, you have successfully created React 3d Model Viewer. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply