3d avec webgl + mesh

Description

Avant toute chose : cette source est un test et dispose de grosse erreur de conception, et des manque dûe à une maitrise imparfait du comportement de WebGL.

Maintenant passons aux choses interessantes :
- Importation de fichier X (Modèle 3D sur un formalise DirectX textuel)
- Gestion camera en vue à la 1ere ou 3eme personne
- Texturing
- Gestion de "ciel"
- Implementation de collision rudimentaires basé sur de la 2D (vue de dessus) sur un calcul d' "empatement" cubique (seulement sur les axes X/Z)
- Gestion d'un File.x mesh comme matrice de sol
- Manipulation des File.x mesh

Les points negatifs :
- Le code manque de commentaires (mais pour ca malheuresement, il y a un tel volume que tout commenté rend le code illisible -__-)
- Gros problème de gestion de la lumière (défaut du en partie à une mauvaise gestion de transformations des vecteur normaux)
- Parfois quelques rattage des transformations du à une gestion synchrone et asynchorones des operations sur le moteur (que j'ai aussi codé et qui parfois se rate un peu aussi)
- Collision au sol un peu approximative, car les calcul d'intersection de droite et de plan revienne lourd pour un grand nombre de facette
- Decoupage en objet/sous objet discutable au niveau analytique
- Ne gère pas les modèle multi-textures (pas pris en compte dans la methode d'importation)
- Ne gère pas les materials/map bumping/texture shader
- Pas prevu pour l'implementation de l'alphabending (mais c'est codé au niveau moteur)
- Vous aurez besoin d'un serveur HTTP, car Ajax ne charge pas les fichier locaux
- Vous aurez besoin d'activer WebGL sous firefox

Les contraintes au niveau navigateur sont les mêmes que pour cette source précedente :
http://www.javascriptfr.com/codes/3D-AVEC-WEBGL_53335.aspx

Pour ceux qui veulent tester sous de suite sans lire le code (oh oui je vous comprend)
- Maintenez le clic droit pour que je mouvement de la souris se repercute sur l'angle de la camera
- Avancer/reculer/gauche/droite : Touches R/F/D/G
- Reculer/avancer la vue à la 3eme personne : molette souris
- Modifier les post effet sur textures : Touches 1/2/3/5/6 (1 : normal)

Attention de ne pas poussez le FPS trop haut, certaines actions du moteur de font en plusieurs top pour des question de performances, donc risque d'anomalie sur un FPS trop elevé

Source / Exemple :


// Juste en JS le fichier de lancement et de boucle principal....tout simple, non ?

var gui = 			null;
var fps = 			null;
var camera = 		null;
var map = 			null;

function Start(){

	fps = 		new Fps(10);
	gui = 		new Gui('html_gui');
	camera = 	new Camera();
	map = 		new Map('e2d_gui', 'e3d_background', 'e3d_scene', function(e){ console.log(e); });
	
	EventsListener.CaptureStart(window);	// Capture d'evenements
	EventsListener.ContextMenuLock();		// Bloque le menu contextuel

	XHR.SetCache(true);						// Active le cache fichier (pour eviter les chargement multiples)
	LoadLights3D();							// Charge les lumières
	LoadObject3D();							// Charge la scene
	XHR.ClearCache();						// Vide le cache fichier

	FullScreen();							// Maintient l'interface a la taille de la fenetre
	Loading();								// Attend la fin du chargement			

}
function FullScreen(){
	window.onresize = function(){
		var main = document.getElementById('main');
		var width = main.offsetWidth;
		var height = main.offsetHeight;
		var coef = width/height
		if(coef>document.body.offsetWidth/document.body.offsetHeight){
			// Fullscreen Paysage
			width = document.body.offsetWidth;
			height = Math.round(width/coef);
		} else {
			// Fullscreen Portrait
			height = document.body.offsetHeight;
			width = Math.round(height*coef);
		}
		main.style.display = 'none';
		main.style.width = width + 'px';
		main.style.height = height + 'px';
		main.style.display = 'block';
	}
	window.onresize();
}

function LoadLights3D(){
	map.setAmbiantLighting(0.8, 0.8, 0.8);
	//map.setPointLighting('lux1', 0, 5, 0, 0.3, 0.3, 0.3);
}

function LoadObject3D(){
	map.LoadMapFileX('./mesh/map.x');						// Fichier de sol
	map.LoadBackgroundFileX('./mesh/background.x');			// Fichier de fond 3D

	map.LoadObjectFileX('player', './mesh/pointeur.x');		// Un objet 3D servant de pointeur de joueur
	map.setObjetCollision('player', true);					// Active la collision cubique

	map.LoadObjectFileX('caisse0', './mesh/caisse.x');		// Un objet
	map.ScaleObject('caisse0', 0.4, 0.4, 0.4);				// Etirement
	map.TranslateObjectTo('caisse0', 20, 0, -20);			// Translation
	map.RotateObjectTo('caisse0', 0, 0.4, 0);				// Rotation
	map.setObjetCollision('caisse0', true);					// Active la collision cubique

	map.LoadObjectFileX('caisse1', './mesh/caisse.x');		// Un objet
	map.ScaleObject('caisse1', 0.3, 0.3, 0.3);				// Etirement
	map.TranslateObjectTo('caisse1', 10, 0, -20);			// Translation
	map.RotateObjectTo('caisse1', 0, -0.4, 0);				// Rotation
	map.setObjetCollision('caisse1', true);					// Active la collision cubique
	
	map.LoadObjectFileX('potence', './mesh/potence.x');		// Un objet
	map.ScaleObject('potence', 3, 3, 3);					// Etirement
	map.TranslateObjectTo('potence', -54, 7, 5);			// Translation
	map.RotateObjectTo('potence', 0, 1.57, 0);				// Rotation
	map.setObjetCollision('potence', true);					// Active la collision cubique
	
}
function Loading(){
	if(map.Loaded()){
		Loop();					// Lance la boucle principale
	} else {
		setTimeout('Loading()', 200);
	}
}
function Loop(){

	// Comportement au clavier
	var keys = EventsListener.KeysPressed();
	for(key in keys){
		key = keys[key];
		switch(key){
			// Effet sur les textures
			case 49: map.setTextureEffect('NONE'); break; 		// Touche 1
			case 50: map.setTextureEffect('GRAYSCALE'); break;	// Touche 2
			case 51: map.setTextureEffect('NEGATIVE'); break;   // Touche 3
			case 53: map.setTextureEffect('SATURATE'); break;	// Touche 5
			case 54: map.setTextureEffect('WIREGRID'); break;	// Touche 6
			// Deplacement de l'objet principal (avec application de collision)
			case 82: map.MoveObject('player', 1); break; 		// Touche R
			case 68: map.StrafeObject('player', -1); break;		// Touche D
			case 70: map.MoveObject('player', -1); break;		// Touche F
			case 71: map.StrafeObject('player', 1); break;		// Touche G
		}
	}		
	
	// Gestion camera a la souris
	var p = map.getObjectPosition('player');
	p.y += camera.height;
	camera.SyncEvent(EventsListener, p);

	// Rotation de l'objet selon l'angle de la camera
	map.RotateObjectTo('player', 0, camera.angle.y, 0);
	
	// Map
	map.Redraw2D(camera, {x:590, y:10, width: 200, height: 150}, 1.5);
	map.Redraw3D(camera);
	
	// Bouge le pointeur de joueur
	map.TranslateObjectTo('player', camera.look_at.x, camera.look_at.y-camera.height, camera.look_at.z);
	
	// Affichage
	gui.Clear();
	gui.Write('FPS  '+fps.FPS());
	gui.Write('');
	gui.Write('Camera px:'+camera.position.x);
	gui.Write('Camera py:'+camera.position.y);
	gui.Write('Camera pz: '+camera.position.z);
	gui.Write('');
	gui.Write('Camera ax:'+camera.angle.x);
	gui.Write('Camera ay:'+camera.angle.y);
	gui.Write('Camera az: '+camera.angle.z);
	gui.Write('');
	gui.Write('Camera Thrid Person far :'+camera.distance);
	gui.Write('');
	gui.Write('Texture effect: '+map.getTextureEffect());
	
	// Bouclage
	EventsListener.CaptureRelease();
	fps.FPS_Loop('Loop()');
}

Conclusion :


La encore, c'est experimental, mais entrevoir les capacité de WebGL reste très stimulant, notamment dans le domaine du jeu.
Amis geek, regalez vous !

Vous devrez tout de même pour compendre cette source en detail avoir deja de bonne base en moteur 3D (trigonometrie, matrices, buffer, connaissance des decoupes de type vertex/faces, etc...)

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.