Inscription / Connexion Nouveau Sujet
Niveau algorithmique
Partager :

Rasterisation en Javascript

Posté par
adsofts
07-04-11 à 10:43

Bonjour tout le monde,

Bon, je sais que mon problème n'est pas purement mathématique, dès lors, je ne suis pas certain que ce post ai sa place sur ce forum, et si ce n'est pas le cas, je m'en excuse.

En fait voila, je suis développeur, et pour les besoins d'une application Web, je dois faire un mini moteur 3D Javascript. Avant de crier au scandale laissez moi m'expliquer: Je ne veux pas faire de vertex ou autre particules, j'ai juste besoin de projeter des points 3D sur un plan 2D en tenant compte des angles de rotation X et Y de la caméra...rien d'autre que quelques calculs matriciels.
N'étant pas à votre niveau en mathématique, j'ai suivi un article de Wikipedia donnant le principe de la rasterisation ainsi que les principales matrices de transformation à utiliser (http://fr.wikipedia.org/wiki/Rast%C3%A9risation#Voir_aussi)

Je me suis donc coder mon truc en Javascript mais évidement, ca marche po

J'ai pourtant vérifier l'ensemble de mes calculs, tout me semble correct....je commence donc à me dire que c'est peut etre le principe meme utilisé qui n'est pas le bon, on pas bien compris dans son implémentation, c'est pourquoi j'ai eu l'idée de faire appel à mes "matheux" (qui accessoirement peuvent lire du code JavaScript, mais ca j'ai pas trop de doute)


Voila, bah si vous avez le temps et l'envie de m'aider, ca serait super sympa

Merci par avance

Voici le code JS (je suis désolé, ce forum n'étant pas prévu pour du code, il n'y à pas de balise spécialisée, du coup je suis obligé d'utiliser celle pour la citation qui supprime toutes les indentations...si vous voulez le code originel, envoyer moi un MP, et je vous le donnerai par mail):

Citation :

var ads3d = new function() {

/*** Propriété ***/

// Tableau contenant la liste des vecteurs (Point) à afficher
this.plotsList = new Array();
//Permet d'accéder aux différent paramètres du viewport (zone d'affichage)
this.viewport = function() {
this.domReference = null; //Reference vers le contener DOM affichant le viewport (DIV)
this.minWidth = 0; //Position des pixels du bord gauche du viewport
this.maxWidth = 0; //Position des pixels du bord droit du viewport
this.minHeight = 0; //Position des pixels du bord bas du viewport
this.maxHeight = 0; //Position des pixels du bord haut du viewport
this.minDist = 0; //Distance depuis la caméra à partir delaquelle on commence à "voir" les objets 3D
this.maxDist = 500; //Distance maximale depuis la caméra à partir de laquelle on arrète de "voir" les objets
};

this.camera = function() {
//Point ou est placée la caméra
this.origin = null;
//Point ou regarde la caméra
this.target = null;
//Position de la caméra (Droite, couchée à droite, couchée à gauche ou la tete en bas)
this.position = null; //valeur positive non null sur Y, la caméra est droite
//Angle de rotation de la caméra autour de l'axe Y (droite <=> gauche)
this.rotationY = 0.0;
//Angle de rotation de la caméra autour de l'axe X (haut <=> bas)
this.rotationX = 0.0;
};

/*** Methodes ***/

//Permet d'attacher le moteur à la référence vers l'objet DOM passé en argument
this.setViewPort = function(poDomElement) {
this.viewport.domReference = poDomElement;
this.viewport.minWidth = 0;
this.viewport.maxWidth = poDomElement.offsetWidth;
this.viewport.minHeight = 0;
this.viewport.maxHeight = poDomElement.offsetHeight;
this.viewport.minDist = 0;
this.viewport.maxDist = 500;
};

//Ajoute un point en 3D dans le monde aux coordonnées passées en argument
this.add3dPlot = function(piPlotX, piPlotY, piPlotZ) {
this.plotsList.push(new ads3d.vector(piPlotX, piPlotY, piPlotZ));
};

//Effectue tous les calculs de rendu à un instant T et met à jour l'affichage
this.updateViewport = function() {

//On commence par créer la matrice WORLD qui est le produit de toutes les matrices de transformation
//Pour le moment on ne gère que les rotation X et Y
var loMatRotX = new ads3d.matrix(4, 4);
loMatRotX.setToRotationX(this.camera.rotationX);

var loMatRotY = new ads3d.matrix(4, 4);
loMatRotY.setToRotationY(this.camera.rotationY);

var loMatWORLD = loMatRotX.multiplyToMatrix(loMatRotY);
//On parcours maintenant la liste des points 3D dans le monde
for(liPlotIndex in this.plotsList) {

var loPlotVector = this.plotsList[liPlotIndex];

/*** RASTERISATION ETAPE 1 (ModelToWorld) ***/

//On en fait un vecteur unitaire pour que les calculs soient plus propres
loPlotVector = loPlotVector.getUnitVector();

//On passe le point au travers de la matrice WORLD pour lui affecter toutes les transformations (Etape ModelToWorld de la rasterisation)
loPlotVector = loMatWORLD.multiplyToVector(loPlotVector);

/*** RASTERISATION ETAPE 2 (WorldToView) ***/

//On passe maintenant au calcul de la matrice de vue qui permet de transposer le point 3D sur un plan prenant en compte la position et l'orientation de la caméra
//(Etape WorldToView de la rasteritation)
//Pour plus de clareté, j'ai décomposer cette matrice de vue selon les 2 sous matrices (A et B) qui la compose en se multipliant

//On commence par calculer les Vecteurs transposant les paramètres de la caméra
var loVectorF = ads3d.camera.origin.substractToVector(ads3d.camera.target);
var loVectorS = loVectorF.multiplyToVector(ads3d.camera.position);
var loVectorU = loVectorS.multiplyToVector(loVectorF);

//Puis la matrice view en elle meme
var loMatViewPartA = new ads3d.matrix(4, 4);
loMatViewPartA.setToViewMatrixPartA(loVectorS, loVectorU, loVectorF);
var loMatViewPartB = new ads3d.matrix(4, 4);
loMatViewPartB.setToViewMatrixPartB(ads3d.camera.origin);
var loMatView = loMatViewPartA.multiplyToMatrix(loMatViewPartB);

//enfin on passe notre point dans cette view
loPlotVector = loMatView.multiplyToVector(loPlotVector);

/*** RASTERISATION ETAPE 3 (ViewToProjection) ***/
//Cette dernière étape consiste à faire une projection de la matrice View sur le plan du viewport, les tailles de ce dernier sont donc necessaires
var loMatProj = new ads3d.matrix(4, 4);
loMatProj.setToOrthogonalMatrixProjection(this.viewport.minWidth, this.viewport.maxWidth, this.viewport.minHeight, this.viewport.maxHeight, this.viewport.minDist, this.viewport.maxDist);

//Voici enfin le vecteur qui contient les coordonnées 2D pour l'affichage
loPlotVector = loMatProj.multiplyToVector(loPlotVector);

alert("Vector.X: " + loPlotVector.X + " Vector.Y: " + loPlotVector.Y + " Vector.Z: " + loPlotVector.Z);
}
};

/*** Gestion de la caméra ***/
this.initCamera = function() {
//Point ou est placée la caméra
this.camera.origin = new ads3d.vector(0.1, 0.1, 0.1);
//Point ou regarde la caméra
this.camera.target = new ads3d.vector(0, 0, 500);
//Position de la caméra (Droite, couchée à droite, couchée à gauche ou la tete en bas)
this.camera.position = new ads3d.vector(0, 1, 0); //valeur positive non null sur Y, la caméra est droite
//Angle de rotation de la caméra autour de l'axe Y (droite <=> gauche)
this.camera.rotationY = 0.0;
//Angle de rotation de la caméra autour de l'axe X (haut <=> bas)
this.camera.rotationX = 0.0;
};

/*** Gestion d'un Vecteur 3d ***/
this.vector = function(pPosX, pPosY, pPosZ) {
//Coordonnée X du Vecteur
this.X = pPosX;
//Coordonnée Y du Vecteur
this.Y = pPosY;
//Coordonnée Z du Vecteur
this.Z = pPosZ;

//Magnitude du vecteur (distance spaciale du point)
this.Magnitude = function() {
return Math.sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
};

//Permet de récupérer le vecteur unitaire du vecteur considéré
//Retourne un nouveau vecteur
this.getUnitVector = function() {
var liTmp = 1.0 / this.Magnitude();

return new ads3d.vector(
this.X *= liTmp,
this.Y *= liTmp,
this.Z *= liTmp
);
};

//Permet de multiplier le vecteur courant par celui passer en argument.
//Retourne un nouveau vecteur
this.multiplyToVector = function(poVector) {
return new ads3d.vector(
this.X * poVector.X,
this.Y * poVector.Y,
this.Z * poVector.Z
);
};

//Permet d'ajouter le vecteur courant à celui passer en argument
//Retourne un nouveau vecteur
this.addToVector = function(poVector) {
return new ads3d.vector(
this.X + poVector.X,
this.Y + poVector.Y,
this.Z + poVector.Z
);
};

//Permet de soustraire au vecteur courant celui passer en argument
//Retourne un nouveau vecteur
this.substractToVector = function(poVector) {
return new ads3d.vector(
this.X - poVector.X,
this.Y - poVector.Y,
this.Z - poVector.Z
);
};
};

/*** Gestion d'une Matrice ***/
this.matrix = function(pWidth, pHeight) {
//Contenu de la matrice
this.content = new Array();

//Initialisation de la matrice à 0.0
for(var liCptRow = 0; liCptRow < pHeight; liCptRow++) {
this.content[liCptRow] = new Array();
for(var liCptCol = 0; liCptCol < pWidth; liCptCol++) {
this.content[liCptRow][liCptCol] = 0.0;
}
}

//Permet de positionner la matrice comme unitaire
//(ce qui permet qu'elle ne donne pas 0 partout si on la multiplie avec une autre matrice)
this.setToIdentity = function() {
for (var c = 0; c < 4; ++c) {
for (var r = 0; r < 4; ++r) {
this.content[c][r] = (c == r) ? 1.0 : 0.0;
}
}
}

//Permet de positionner la matrice comme une matrice de rotation sur l'axe des X selon l'angle passé en argument
//l'angle est exprimé en degré
this.setToRotationX = function(poAngleDegre) {

var liAngleRadian = Math.PI * poAngleDegre / 180;

this.setToIdentity();

this.content[1][1] = Math.cos(liAngleRadian);
this.content[1][2] = Math.sin(liAngleRadian) * -1.0;
this.content[2][1] = Math.sin(liAngleRadian);
this.content[2][2] = Math.cos(liAngleRadian);
}

//Permet de positionner la matrice comme une matrice de rotation sur l'axe des Y selon l'angle passé en argument
//l'angle est exprimé en degré
this.setToRotationY = function(poAngleDegre) {

var liAngleRadian = Math.PI * poAngleDegre / 180;

this.setToIdentity();

this.content[0][0] = Math.cos(liAngleRadian);
this.content[0][2] = Math.sin(liAngleRadian);
this.content[2][0] = Math.sin(liAngleRadian) * -1.0;
this.content[2][2] = Math.cos(liAngleRadian);
}

//Permet de positionner la matrice comme une matrice de vue (PARTIE A) selon les 3 vecteurs identifiants la caméra et son point de vue
this.setToViewMatrixPartA = function(poVectorS, poVectorU, poVectorF) {

this.content[0][0] = poVectorS.X;
this.content[0][1] = poVectorS.Y;
this.content[0][2] = poVectorS.Z;

this.content[1][0] = poVectorU.X;
this.content[1][1] = poVectorU.Y;
this.content[1][2] = poVectorU.Z;

this.content[2][0] = poVectorF.X * -1.0;
this.content[2][1] = poVectorF.Y * -1.0;
this.content[2][2] = poVectorF.Z * -1.0;

this.content[3][3] = 1.0;
}

//Permet de positionner la matrice comme une matrice de vue (PARTIE B) selon le vecteur de position de la caméra
this.setToViewMatrixPartB = function(poVectorPosCam) {

this.setToIdentity();

this.content[0][3] = poVectorPosCam.X * -1.0;
this.content[1][3] = poVectorPosCam.Y * -1.0;
this.content[2][3] = poVectorPosCam.Z * -1.0;
}

//Permet de positionner la matrice comme une matrice de projection de type Orthogonale en fonction de la taille du viewport
this.setToOrthogonalMatrixProjection = function(piScreenMinWidth, piScreenMaxWidth, piScreenMinHeight, piScreenMaxHeight, piMinDistanceView, piMaxDistanceView) {
this.content[0][0] = 2.0 / (piScreenMaxWidth - piScreenMinWidth);
this.content[0][3] = -1.0  * (piScreenMaxWidth + piScreenMinWidth) / (piScreenMaxWidth - piScreenMinWidth);
this.content[1][1] = 2.0 / (piScreenMaxHeight - piScreenMinHeight);
this.content[1][3] = -1.0  * (piScreenMaxHeight + piScreenMinHeight) / (piScreenMaxHeight - piScreenMinHeight);
this.content[2][2] = -2.0 / (piMaxDistanceView - piMinDistanceView);
this.content[2][3] = -1.0 * (piMaxDistanceView + piMinDistanceView) / (piMaxDistanceView - piMinDistanceView);
this.content[3][3] = 1.0;
}

//Permet de multiplier la matrice courante avec celle passée en argument
//Renvoi une nouvelle matrice
this.multiplyToMatrix = function(poMatrix) {

var loReturnMatrix = new ads3d.matrix(4, 4);

for (var r = 0; r < 4; ++r) {
for (var c = 0; c < 4; ++c) {
for (var k = 0; k < 4; ++k) {
loReturnMatrix.content[c][r] += this.content[k][r] * poMatrix.content[c][k];
}
}
}

return loReturnMatrix;
};

//Permet de multiplier la matrice courante avec le vecteur passé en argument
//Renvoi un nouveau vecteur
this.multiplyToVector = function(poVector) {
return new ads3d.vector(
this.content[0][0] * poVector.X + this.content[1][0] * poVector.Y + this.content[2][0] * poVector.Z + this.content[3][0] * 1.0,
this.content[0][1] * poVector.X + this.content[1][1] * poVector.Y + this.content[2][1] * poVector.Z + this.content[3][1] * 1.0,
this.content[0][2] * poVector.X + this.content[1][2] * poVector.Y + this.content[2][2] * poVector.Z + this.content[3][2] * 1.0
);
};
};
}



function debugMatrix44(poMatrix) {

var oTable = document.createElement('TABLE');

for(liCptRow = 0; liCptRow < 4; liCptRow++) {
var oTR = document.createElement('TR');

for(liCptCol = 0; liCptCol < 4; liCptCol++) {

var oTD = document.createElement('TD');
oTD.innerHTML = poMatrix.content[liCptRow][liCptCol];
oTR.appendChild(oTD);
}

oTable.appendChild(oTR);
}

document.getElementById('DEBUG').appendChild(oTable);
}





window.onload = function() {

ads3d.setViewPort(document.getElementById('viewport'));
ads3d.initCamera();
ads3d.add3dPlot(300, 300, 20);

ads3d.updateViewport();
}


Et le code HTML:

Citation :
<html>
<head>
<script type="text/javascript" src="ads3d.js"></script>
</head>
<body>
<div id="viewport" style="width:600px; height:600px; border:solid 1px #000;"></div>
<div id="DEBUG"></div>

</body>
</html>

Posté par
Tom_Pascal Webmaster
re : Rasterisation en Javascript 07-04-11 à 12:03

Bonjour,

Ouah, en effet, je ne suis pas sûr que tu puisse obtenir beaucoup de réponses, mais pourquoi pas.. l'infographie matricielle reste fortement liée aux mathématiques (quaternions, etc).
Je ne peux pas vraiment t'aider, mais au moins je peux reposter ton code en respectant les identations pour ceux qui veulent le lire plus clairement :

Bon courage.

Rasterisation en Javascript Le code JS :

Citation :
	var ads3d = new function() {

		/*** Propriété ***/
	
		// Tableau contenant la liste des vecteurs (Point) à afficher
		this.plotsList = new Array();
		//Permet d'accéder aux différent paramètres du viewport (zone d'affichage)
		this.viewport = function() {
			this.domReference = null;	//Reference vers le contener DOM affichant le viewport (DIV)
			this.minWidth 	= 0;	//Position des pixels du bord gauche du viewport
			this.maxWidth 	= 0;	//Position des pixels du bord droit du viewport
			this.minHeight 	= 0;	//Position des pixels du bord bas du viewport
			this.maxHeight 	= 0;	//Position des pixels du bord haut du viewport
			this.minDist	= 0;	//Distance depuis la caméra à partir delaquelle on commence à "voir" les objets 3D
			this.maxDist	= 500;	//Distance maximale depuis la caméra à partir de laquelle on arrète de "voir" les objets
		};
		
		this.camera = function() {
			//Point ou est placée la caméra
			this.origin 	= null;
			//Point ou regarde la caméra
			this.target 	= null;
			//Position de la caméra (Droite, couchée à droite, couchée à gauche ou la tete en bas)
			this.position 	= null; //valeur positive non null sur Y, la caméra est droite
			//Angle de rotation de la caméra autour de l'axe Y (droite <=> gauche)
			this.rotationY 	= 0.0;
			//Angle de rotation de la caméra autour de l'axe X (haut <=> bas)
			this.rotationX 	= 0.0;		
		};
		
		/*** Methodes ***/
		
		//Permet d'attacher le moteur à la référence vers l'objet DOM passé en argument
		this.setViewPort = function(poDomElement) {
			this.viewport.domReference = poDomElement;
			this.viewport.minWidth = 0;
			this.viewport.maxWidth = poDomElement.offsetWidth;
			this.viewport.minHeight = 0;
			this.viewport.maxHeight = poDomElement.offsetHeight;
			this.viewport.minDist = 0;
			this.viewport.maxDist = 500;
		};
		
		//Ajoute un point en 3D dans le monde aux coordonnées passées en argument
		this.add3dPlot = function(piPlotX, piPlotY, piPlotZ) {
			this.plotsList.push(new ads3d.vector(piPlotX, piPlotY, piPlotZ));
		};
		
		//Effectue tous les calculs de rendu à un instant T et met à jour l'affichage
		this.updateViewport = function() {
			
			//On commence par créer la matrice WORLD qui est le produit de toutes les matrices de transformation
			//Pour le moment on ne gère que les rotation X et Y
			var loMatRotX = new ads3d.matrix(4, 4);
			loMatRotX.setToRotationX(this.camera.rotationX);
	
			var loMatRotY = new ads3d.matrix(4, 4);
			loMatRotY.setToRotationY(this.camera.rotationY);
				
			var loMatWORLD = loMatRotX.multiplyToMatrix(loMatRotY);			
			//On parcours maintenant la liste des points 3D dans le monde
			for(liPlotIndex in this.plotsList) {
				
				var loPlotVector = this.plotsList[liPlotIndex];
				
				/*** RASTERISATION ETAPE 1 (ModelToWorld) ***/
				
				//On en fait un vecteur unitaire pour que les calculs soient plus propres
				loPlotVector = loPlotVector.getUnitVector();

				//On passe le point au travers de la matrice WORLD pour lui affecter toutes les transformations (Etape ModelToWorld de la rasterisation)
				loPlotVector = loMatWORLD.multiplyToVector(loPlotVector);
				
				/*** RASTERISATION ETAPE 2 (WorldToView) ***/
				
				//On passe maintenant au calcul de la matrice de vue qui permet de transposer le point 3D sur un plan prenant en compte la position et l'orientation de la caméra
				//(Etape WorldToView de la rasteritation)
				//Pour plus de clareté, j'ai décomposer cette matrice de vue selon les 2 sous matrices (A et B) qui la compose en se multipliant
				
				//On commence par calculer les Vecteurs transposant les paramètres de la caméra
				var loVectorF = ads3d.camera.origin.substractToVector(ads3d.camera.target);
				var loVectorS = loVectorF.multiplyToVector(ads3d.camera.position);
				var loVectorU = loVectorS.multiplyToVector(loVectorF);

				//Puis la matrice view en elle meme				
				var loMatViewPartA = new ads3d.matrix(4, 4);
				loMatViewPartA.setToViewMatrixPartA(loVectorS, loVectorU, loVectorF);
				var loMatViewPartB = new ads3d.matrix(4, 4);
				loMatViewPartB.setToViewMatrixPartB(ads3d.camera.origin);
				var loMatView = loMatViewPartA.multiplyToMatrix(loMatViewPartB);

				//enfin on passe notre point dans cette view
				loPlotVector = loMatView.multiplyToVector(loPlotVector);
		
				/*** RASTERISATION ETAPE 3 (ViewToProjection) ***/
				//Cette dernière étape consiste à faire une projection de la matrice View sur le plan du viewport, les tailles de ce dernier sont donc necessaires
				var loMatProj = new ads3d.matrix(4, 4);
				loMatProj.setToOrthogonalMatrixProjection(this.viewport.minWidth, this.viewport.maxWidth, this.viewport.minHeight, this.viewport.maxHeight, this.viewport.minDist, this.viewport.maxDist);
				
				//Voici enfin le vecteur qui contient les coordonnées 2D pour l'affichage
				loPlotVector = loMatProj.multiplyToVector(loPlotVector);
				
				alert("Vector.X: " + loPlotVector.X + " Vector.Y: " + loPlotVector.Y + " Vector.Z: " + loPlotVector.Z);
			}
		};
				
		/*** Gestion de la caméra ***/
		this.initCamera = function() {
			//Point ou est placée la caméra
			this.camera.origin = new ads3d.vector(0.1, 0.1, 0.1);
			//Point ou regarde la caméra
			this.camera.target = new ads3d.vector(0, 0, 500);
			//Position de la caméra (Droite, couchée à droite, couchée à gauche ou la tete en bas)
			this.camera.position = new ads3d.vector(0, 1, 0); //valeur positive non null sur Y, la caméra est droite
			//Angle de rotation de la caméra autour de l'axe Y (droite <=> gauche)
			this.camera.rotationY = 0.0;
			//Angle de rotation de la caméra autour de l'axe X (haut <=> bas)
			this.camera.rotationX = 0.0;
		};
		
		/*** Gestion d'un Vecteur 3d ***/
		this.vector = function(pPosX, pPosY, pPosZ) {
			//Coordonnée X du Vecteur
			this.X = pPosX;
			//Coordonnée Y du Vecteur
			this.Y = pPosY;
			//Coordonnée Z du Vecteur
			this.Z = pPosZ;
			
			//Magnitude du vecteur (distance spaciale du point)
			this.Magnitude = function() {
				return Math.sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
			};
		
			//Permet de récupérer le vecteur unitaire du vecteur considéré
			//Retourne un nouveau vecteur
			this.getUnitVector = function() {
				var liTmp = 1.0 / this.Magnitude();
				
				return new ads3d.vector(
					this.X *= liTmp,
					this.Y *= liTmp,
					this.Z *= liTmp
				);
			};
			
			//Permet de multiplier le vecteur courant par celui passer en argument.
			//Retourne un nouveau vecteur
			this.multiplyToVector = function(poVector) {
				return new ads3d.vector(
					this.X * poVector.X,
					this.Y * poVector.Y,
					this.Z * poVector.Z
				);
			};
			
			//Permet d'ajouter le vecteur courant à celui passer en argument
			//Retourne un nouveau vecteur
			this.addToVector = function(poVector) {
				return new ads3d.vector(
					this.X + poVector.X,
					this.Y + poVector.Y,
					this.Z + poVector.Z					
				);
			};
			
			//Permet de soustraire au vecteur courant celui passer en argument
			//Retourne un nouveau vecteur
			this.substractToVector = function(poVector) {
				return new ads3d.vector(
					this.X - poVector.X,
					this.Y - poVector.Y,
					this.Z - poVector.Z					
				);
			};
		};
		
		/*** Gestion d'une Matrice ***/
		this.matrix = function(pWidth, pHeight) {
			//Contenu de la matrice
			this.content = new Array();
			
			//Initialisation de la matrice à 0.0
			for(var liCptRow = 0; liCptRow < pHeight; liCptRow++) {
				this.content[liCptRow] = new Array();
				for(var liCptCol = 0; liCptCol < pWidth; liCptCol++) {
					this.content[liCptRow][liCptCol] = 0.0;
				}
			}
			
			//Permet de positionner la matrice comme unitaire 
			//(ce qui permet qu'elle ne donne pas 0 partout si on la multiplie avec une autre matrice)
			this.setToIdentity = function() {
				for (var c = 0; c < 4; ++c) {
					for (var r = 0; r < 4; ++r) {
						this.content[c][r] = (c == r) ? 1.0 : 0.0;
					}
				}
			}
			
			//Permet de positionner la matrice comme une matrice de rotation sur l'axe des X selon l'angle passé en argument
			//l'angle est exprimé en degré
			this.setToRotationX = function(poAngleDegre) {
			
				var liAngleRadian = Math.PI * poAngleDegre / 180;
				
				this.setToIdentity();

				this.content[1][1] = Math.cos(liAngleRadian);
				this.content[1][2] = Math.sin(liAngleRadian) * -1.0;
				this.content[2][1] = Math.sin(liAngleRadian);
				this.content[2][2] = Math.cos(liAngleRadian);
			}
			
			//Permet de positionner la matrice comme une matrice de rotation sur l'axe des Y selon l'angle passé en argument
			//l'angle est exprimé en degré			
			this.setToRotationY = function(poAngleDegre) {
			
				var liAngleRadian = Math.PI * poAngleDegre / 180;
				
				this.setToIdentity();
				
				this.content[0][0] = Math.cos(liAngleRadian);
				this.content[0][2] = Math.sin(liAngleRadian);
				this.content[2][0] = Math.sin(liAngleRadian) * -1.0;
				this.content[2][2] = Math.cos(liAngleRadian);
			}
			
			//Permet de positionner la matrice comme une matrice de vue (PARTIE A) selon les 3 vecteurs identifiants la caméra et son point de vue
			this.setToViewMatrixPartA = function(poVectorS, poVectorU, poVectorF) {
			
				this.content[0][0] = poVectorS.X;
				this.content[0][1] = poVectorS.Y;
				this.content[0][2] = poVectorS.Z;
				
				this.content[1][0] = poVectorU.X;
				this.content[1][1] = poVectorU.Y;
				this.content[1][2] = poVectorU.Z;
				
				this.content[2][0] = poVectorF.X * -1.0;
				this.content[2][1] = poVectorF.Y * -1.0;
				this.content[2][2] = poVectorF.Z * -1.0;

				this.content[3][3] = 1.0;
			}
			
			//Permet de positionner la matrice comme une matrice de vue (PARTIE B) selon le vecteur de position de la caméra
			this.setToViewMatrixPartB = function(poVectorPosCam) {
			
				this.setToIdentity();
				
				this.content[0][3] = poVectorPosCam.X * -1.0;
				this.content[1][3] = poVectorPosCam.Y * -1.0;
				this.content[2][3] = poVectorPosCam.Z * -1.0;
			}
			
			//Permet de positionner la matrice comme une matrice de projection de type Orthogonale en fonction de la taille du viewport
			this.setToOrthogonalMatrixProjection = function(piScreenMinWidth, piScreenMaxWidth, piScreenMinHeight, piScreenMaxHeight, piMinDistanceView, piMaxDistanceView) {
					this.content[0][0] = 2.0 / (piScreenMaxWidth - piScreenMinWidth);
					this.content[0][3] = -1.0  * (piScreenMaxWidth + piScreenMinWidth) / (piScreenMaxWidth - piScreenMinWidth);
					this.content[1][1] = 2.0 / (piScreenMaxHeight - piScreenMinHeight);
					this.content[1][3] = -1.0  * (piScreenMaxHeight + piScreenMinHeight) / (piScreenMaxHeight - piScreenMinHeight);
					this.content[2][2] = -2.0 / (piMaxDistanceView - piMinDistanceView);
					this.content[2][3] = -1.0 * (piMaxDistanceView + piMinDistanceView) / (piMaxDistanceView - piMinDistanceView);
					this.content[3][3] = 1.0;
			}
			
			//Permet de multiplier la matrice courante avec celle passée en argument
			//Renvoi une nouvelle matrice
			this.multiplyToMatrix = function(poMatrix) {
				
				var	loReturnMatrix = new ads3d.matrix(4, 4);

				for (var r = 0; r < 4; ++r) {
					for (var c = 0; c < 4; ++c) {
						for (var k = 0; k < 4; ++k) {
							loReturnMatrix.content[c][r] += this.content[k][r] * poMatrix.content[c][k];
						}
					}
				}
				
				return loReturnMatrix;			
			};
			
			//Permet de multiplier la matrice courante avec le vecteur passé en argument
			//Renvoi un nouveau vecteur
			this.multiplyToVector = function(poVector) {
				return new ads3d.vector(
					this.content[0][0] * poVector.X + this.content[1][0] * poVector.Y + this.content[2][0] * poVector.Z + this.content[3][0] * 1.0,
					this.content[0][1] * poVector.X + this.content[1][1] * poVector.Y + this.content[2][1] * poVector.Z + this.content[3][1] * 1.0,
					this.content[0][2] * poVector.X + this.content[1][2] * poVector.Y + this.content[2][2] * poVector.Z + this.content[3][2] * 1.0
				);			
			};
		};
	}
	
	
	
	function debugMatrix44(poMatrix) {
	
		var oTable = document.createElement('TABLE');
		
		for(liCptRow = 0; liCptRow < 4; liCptRow++) {
			var oTR = document.createElement('TR');
			
			for(liCptCol = 0; liCptCol < 4; liCptCol++) {
			
				var oTD = document.createElement('TD');
				oTD.innerHTML = poMatrix.content[liCptRow][liCptCol];
				oTR.appendChild(oTD);
			}
			
			oTable.appendChild(oTR);
		}
		
		document.getElementById('DEBUG').appendChild(oTable);
	}
	
	
	
	
	
	window.onload = function() {
		
		ads3d.setViewPort(document.getElementById('viewport'));
		ads3d.initCamera();
		ads3d.add3dPlot(300, 300, 20);
		
		ads3d.updateViewport();
	}


Rasterisation en Javascript Le code HTML :

Citation :
<html>
	<head>
		<script type="text/javascript" src="ads3d.js"></script>
	</head>
	<body>
		<div id="viewport" style="width:600px; height:600px; border:solid 1px #000;"></div>
		<div id="DEBUG"></div>
	
	</body>
</html>

Posté par
adsofts
re : Rasterisation en Javascript 07-04-11 à 12:11

salut,

Merci pour l'indentation, effectivement c'est plus clair comme ca

Je sais bien que m'a demande est un peu particulière pour ce forum, mais je pense que mon problème se situe bel et bien au niveau des matrices et de leur calcul (donc au niveau mathématique), j'ai donc espoir que l'un d'entre vous un peu courageux acceptera de lire et comprendre le code (je pense qu'avec un esprit scientifique ce code est compréhensible sans avoir de fortes notions de programmation)...

Toujours est-il que les informations sur ce type de développement sur le web sont vraiment très minces... quelques librairies font déja tout ce travail et surtout, rare sont ceux qui tente l'expérience avec du simple Javascript (c'est vrai qu'a premier abord ca parait stupide ) du coup ,j'ai vraiment beaucoup de mal à trouver de l'aide, alors je frappe aux portes qui me paraissent les moins mal placées..

Posté par
caylus
re : Rasterisation en Javascript 19-05-11 à 15:47

Bonjour adsofts,

Je me suis penché sur votre problème, mais j'ai quelques questions:
1: je n'ai pas compris le calcul de la matrice de projection

Citation :

this.setToOrthogonalMatrixProjection = function(piScreenMinWidth, piScreenMaxWidth, piScreenMinHeight, piScreenMaxHeight, piMinDistanceView, piMaxDistanceView)
{
this.content[0][0] = 2.0 / (piScreenMaxWidth - piScreenMinWidth);
this.content[0][3] = -1.0  * (piScreenMaxWidth + piScreenMinWidth) / (piScreenMaxWidth - piScreenMinWidth);
this.content[1][1] = 2.0 / (piScreenMaxHeight - piScreenMinHeight);
this.content[1][3] = -1.0  * (piScreenMaxHeight + piScreenMinHeight) / (piScreenMaxHeight - piScreenMinHeight);
this.content[2][2] = -2.0 / (piMaxDistanceView - piMinDistanceView);
this.content[2][3] = -1.0 * (piMaxDistanceView + piMinDistanceView) / (piMaxDistanceView - piMinDistanceView);
this.content[3][3] = 1.0;
};


2:  // RASTERISATION ETAPE 2 (WorldToView)
Ne devrait pas être effectuée pour chaque vecteur
mais une seule fois dés l'initialisation de la camera

3: Ne faudrait-il pas créer plusieurs classes:
- vector
- mat4
- Box3d

4: Comment allez-vous afficher les vecteurs en HTML?

Je poursuis le développement qui peut être téléchargé à


@+ Michel

Posté par
adsofts
re : Rasterisation en Javascript 19-05-11 à 16:13

Bonjour Michel,

Merci d'avoir prit le temps de regarde mon code.

A vrai dire, j'avais oublier que j'avais poster ici...
En fait, j'ai finalement réussis à faire ce que je voulais, une version (avec encore quelques bugs) est visible ici: http://www.australe.fr/space/ (bouger avec la souris)

Je n'ai plus de problème en ce qui concerne la 3D en soit...

Merci encore



Vous devez être membre accéder à ce service...

Pas encore inscrit ?

1 compte par personne, multi-compte interdit !

Ou identifiez-vous :


Rester sur la page

Désolé, votre version d'Internet Explorer est plus que périmée ! Merci de le mettre à jour ou de télécharger Firefox ou Google Chrome pour utiliser le site. Votre ordinateur vous remerciera !