Vecteur 3d - rotation dans l'espace et coordonnées polaires

Soyez le premier à donner votre avis sur cette source.

Vue 32 015 fois - Téléchargée 2 048 fois

Description

Salut tout le monde,
Ce programme montre comment tracer un vecteur, et comment tracer un plan qui lui est perpendiculaire (le petit carré)
Pour y arriver, j'utilise les coordonnées polaires (longitude et latitude) ainsi que la multiplication par les matrices de rotation

Le code source est simple et bien structuré (selon moi ;)
j'espère que vous aller apprecier

Je tiens à remercier mon père qui a donné généreusement de son temps pour le débogage de cette application qui semblait vouée à l'échec :p

Source / Exemple :


using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace tube3d
{
public class directxGestion
{
//device pour l'affichage
private Device device = null;
//handle sur la surface d'affichage
private IntPtr handle;
//buffer de vecteur pour les axes x, y, z
private VertexBuffer axes = null;
//buffer de vecteur pour le carré
private VertexBuffer square = null;
//buffer de vecteur pour le vecteur
private VertexBuffer vecteur = null;
public int x1=0, y1=0, z1=0;
public int x2=0, y2=0, z2=4;
public int cameraX = 2, cameraY = 2, cameraZ = 5;
private double latitude = Math.PI/2, longitude = 0;
private float[,] squarePoints = new float[4,3] {{-2,2,0},{2,2,0},{-2,-2,0},{2,-2,0}};

#region CustomVertex
const VertexFormats customVertexFormat = VertexFormats.Position | VertexFormats.Diffuse | VertexFormats.Texture1;
private struct CustomVertex 
{
	public float X;
	public float Y;
	public float Z;
	public int color;			
	public float tu;
	public float tv;
}
private CustomVertex CreateVertex(float x, float y, float z, float tu, float tv, int color)
{
	CustomVertex custVertex = new CustomVertex();
	custVertex.X = x; custVertex.Y = y; custVertex.Z = z;
	custVertex.color = color;
	custVertex.tu = tu; custVertex.tv = tv;
	return custVertex;
}
#endregion

public directxGestion(IntPtr handle)
{
	this.handle = handle;			
}

#region InitDevice
public bool InitDevice(bool fullscreen)
{
	DisplayMode DispMode = Manager.Adapters[Manager.Adapters.Default.Adapter].CurrentDisplayMode;
	PresentParameters presentParams = new PresentParameters();
	if(fullscreen) {presentParams.BackBufferFormat = DispMode.Format; presentParams.BackBufferWidth = DispMode.Width; presentParams.BackBufferHeight = DispMode.Height;}
	
	//on veut que notre device supporte la profondeur
	presentParams.AutoDepthStencilFormat = DepthFormat.D16;
	presentParams.EnableAutoDepthStencil = true;

	//mode fenetre
	if(!fullscreen) presentParams.Windowed = true;
	//mode de switchage de buffer
	presentParams.SwapEffect = SwapEffect.Discard;
	//attendre la synchronisation avec l'ecran (VSync)
	//utiliser PresentInterval.Immediate pour des vitesses rapides
	presentParams.PresentationInterval = PresentInterval.One;
	
	try
	{
		//on crée le device selon les paramètres de présentation si-dessus
		if(fullscreen) device = new Device(Manager.Adapters.Default.Adapter, DeviceType.Hardware, this.handle, CreateFlags.SoftwareVertexProcessing, presentParams);
		else device = new Device(Manager.Adapters.Default.Adapter, DeviceType.Hardware, this.handle, CreateFlags.SoftwareVertexProcessing, presentParams);
		//on lui associe notre format de vecteur spécial
		device.VertexFormat = customVertexFormat;
		//on active le z-buffer
		device.RenderState.ZBufferEnable = false;
		//pas de culling
		device.RenderState.CullMode = Cull.None;
		//mode de remplissage des polygones (ici solide)
		device.RenderState.FillMode = FillMode.Solid;
		//pas de lumière
		device.RenderState.Lighting = false;	
						
		//activation de l'alpha blending
		device.RenderState.AlphaBlendEnable = true;
		device.RenderState.DestinationBlend = Blend.DestinationAlpha;
		device.RenderState.SourceBlend = Blend.SourceAlpha;
		
		//on définit le mode de projection
		device.Transform.Projection = Matrix.OrthoLH(20,20,100,-100);
		//on positionne la caméra
		device.Transform.View = Matrix.LookAtLH(new Vector3(-cameraX,-cameraY,-cameraZ), new Vector3(0,0,0), new Vector3(0,1,0));
	}
	catch
	{
		return false;
	}
	
	return true;
}
#endregion

#region Initialisation des vertexBuffer
#region InitBuffers
public void InitBuffers()
{
	//on crée les buffers qui va contenir nos vecteurs
	axes = new VertexBuffer(typeof(CustomVertex), 6, device, Usage.WriteOnly, customVertexFormat, Pool.Default);
	square = new VertexBuffer(typeof(CustomVertex), 4, device, Usage.WriteOnly, customVertexFormat, Pool.Default);
	vecteur = new VertexBuffer(typeof(CustomVertex), 2, device, Usage.WriteOnly, customVertexFormat, Pool.Default);
	//on associe à une fonction, la création de notre buffer
	//au cas qu'il soit perdu
	axes.Created += new EventHandler(this.CreateAxes);
	square.Created += new EventHandler(this.CreateSquare);
	vecteur.Created += new EventHandler(this.CreateVector);
	//on force la création du buffer
	CreateAxes(axes, null);
	CreateSquare(square, null);
	CreateVector(vecteur, null);
}
#endregion
#region creation des 3 axes
private void CreateAxes(object sender, EventArgs e)
{
	CustomVertex[] verts = new CustomVertex[6];
	//axe des x
	verts[0] = CreateVertex(0,0,0,0,0, Color.FromArgb(100, Color.LightBlue).ToArgb());
	verts[1] = CreateVertex(10,0,0,0,0, Color.FromArgb(100, Color.LightBlue).ToArgb());
	//axe des y
	verts[2] = CreateVertex(0,0,0,0,0, Color.FromArgb(100, Color.LightGreen).ToArgb());
	verts[3] = CreateVertex(0,10,0,0,0, Color.FromArgb(100, Color.LightGreen).ToArgb());
	//axe des z
	verts[4] = CreateVertex(0,0,0,0,0, Color.FromArgb(100, Color.Red).ToArgb());
	verts[5] = CreateVertex(0,0,20,0,0, Color.FromArgb(100, Color.Red).ToArgb());
	axes.SetData(verts, 0, LockFlags.None);
}
#endregion
#region creation du carré
private void CreateSquare(object sender, EventArgs e)
{
	CustomVertex[] verts = new CustomVertex[4];
	float x=0, y=0, z=0;
	float x1=0, y1=0, z1=0;
	Matrix rotX = Matrix.RotationX((float)(latitude-Math.PI/2));
	Matrix rotY = Matrix.RotationY((float)longitude);
	for(int i=0; i<4; i++)
	{
		x1 = squarePoints[i,0] * rotX.M11 + squarePoints[i,1] * rotX.M21 + squarePoints[i,2] * rotX.M31;
		y1 = squarePoints[i,0] * rotX.M12 + squarePoints[i,1] * rotX.M22 + squarePoints[i,2] * rotX.M32;
		z1 = squarePoints[i,0] * rotX.M13 + squarePoints[i,1] * rotX.M23 + squarePoints[i,2] * rotX.M33;
			x = x1 * rotY.M11 + y1 * rotY.M21 + z1 * rotY.M31;
			y = x1 * rotY.M12 + y1 * rotY.M22 + z1 * rotY.M32;
			z = x1 * rotY.M13 + y1 * rotY.M23 + z1 * rotY.M33;
		x+=this.x1; y+=this.y1; z+=this.z1;
		verts[i] = CreateVertex(x,y,z,0,0, Color.FromArgb(150, Color.White).ToArgb());
		
	}
	square.SetData(verts, 0, LockFlags.None);
}
#endregion
#region creation du vecteur
private void CreateVector(object sender, EventArgs e)
{
	CustomVertex[] verts = new CustomVertex[2];
	verts[0] = CreateVertex(x1,y1,z1,0,0, Color.FromArgb(255, Color.Yellow).ToArgb());
	verts[1] = CreateVertex(x2,y2,z2,0,0, Color.FromArgb(255, Color.Yellow).ToArgb());
	vecteur.SetData(verts, 0, LockFlags.None);
}
#endregion
#endregion

#region Render
public void Render()
{
	if(device==null) return;
	
	
	//on efface l'écran et le z-buffer
	device.Clear(ClearFlags.Target|ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
	//on commence la scène
	device.BeginScene();
	//-----------------------------------------------------
	device.SetStreamSource(0, axes, 0);
		device.DrawPrimitives(PrimitiveType.LineList, 0, 3);
	//-----------------------------------------------------
	//this.RotationMatrices((int)(this.latitude*180/Math.PI), (int)(this.longitude*180/Math.PI), 0);
	device.SetStreamSource(0, square, 0);
		device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
	//device.Transform.World = Matrix.Identity;
	//-----------------------------------------------------
	device.SetStreamSource(0, vecteur, 0);
		device.DrawPrimitives(PrimitiveType.LineList, 0, 1);
	//on termine le dessin
	device.EndScene();
	//on l'affiche à l'écran
	try{device.Present();}
	catch{}
	using(Graphics g = Graphics.FromHwnd(this.handle))
	{
		string str = string.Format("latitude :\t\t{0} degré(s)\nlongitude :\t{1} degré(s)", Math.Round(latitude*180/Math.PI, 0), Math.Round(longitude*180/Math.PI, 0));
		g.DrawString(str, new System.Drawing.Font(FontFamily.GenericSansSerif, 12), new SolidBrush(Color.White), new Point(0,0));
	}
}
#endregion
public void Invalidate()
{
	int x = x2 - x1; int y = y2 - y1; int z = z2 - z1;
	this.latitude = Math.Atan2(Math.Sqrt(x*x+z*z), y);
	this.longitude = Math.Atan2(x, z);
	this.CreateVector(null, null);
	this.CreateSquare(null, null);
}
public void SetCamera()
{
	device.Transform.View = Matrix.LookAtLH(new Vector3(-cameraX,-cameraY,-cameraZ), new Vector3(0,0,0), new Vector3(0,1,0));
}

}
}

Conclusion :


vous devez avoir DirectX 9.0c
les DLL pour le managed DirectX sont inclus
si vous rencontrez des problèmes, faites moi signe.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
survcopt Messages postés 224 Date d'inscription mardi 27 mai 2003 Statut Membre Dernière intervention 13 mai 2022 1
19 nov. 2008 à 14:27
Excellent ton code , j'ai commencé à le lire plus en détail
comment je peux rajouter une boule à l'origine et remplacer le vecteur par une flèche (cylindre + cône)
Gefkuz Messages postés 61 Date d'inscription samedi 23 juillet 2005 Statut Membre Dernière intervention 18 mars 2019
1 août 2006 à 23:14
Ce code a l'air tres interressant, mais il ne fonctionne pas sous visual 8...

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.