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

Soyez le premier à donner votre avis sur cette source.

Vue 30 296 fois - Téléchargée 1 757 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

Gefkuz
Messages postés
61
Date d'inscription
samedi 23 juillet 2005
Statut
Membre
Dernière intervention
18 mars 2019
-
Ce code a l'air tres interressant, mais il ne fonctionne pas sous visual 8...
survcopt
Messages postés
223
Date d'inscription
mardi 27 mai 2003
Statut
Membre
Dernière intervention
3 juin 2019
-
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)

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.