/// <summary> /// multiplies values of p1 with v /// </summary> public static Point3 operator *(Point3 p1, double v) { Point3 p3 = new Point3(0, 0, 0); p3.x = p1.x * (float)v; p3.y = p1.y * (float)v; p3.z = p1.z * (float)v; return p3; }
public override void Init() { Point3 SunPos = new Point3(); Point3 SunDir = new Point3(); Sun = new oDBSun(SunPos, SunDir, 20f, PlanetAdvanced2.initSunMass, -9.81f); Objects.Add(Sun); Cam.Z = 50000f; }
/// <summary> /// Rotationsmatrix /// </summary> /// <param name="angle">Drehwinkel</param> /// <param name="rotachs">Achse um die gedreht werden soll</param> public void RotMatrix(float angle, Point3 rotachs) { double fangle = (angle * Math.PI) / 180; float fsin = (float)Math.Sin(fangle); float fcos = (float)Math.Cos(fangle); float x = rotachs.x; float y = rotachs.y; float z = rotachs.z; Value[0, 0] = fcos + (float)Math.Pow(x, 2) * (1f - fcos); Value[1, 0] = x * y * (1f - fcos) - z * fsin; Value[2, 0] = x * z * (1f - fcos) + y * fsin; Value[0, 1] = y * x * (1f - fcos) + z * fsin; Value[1, 1] = fcos + (float)Math.Pow(y, 2) * (1f - fcos); Value[2, 1] = y * z * (1f - fcos) * x * fsin; Value[0, 2] = z * x * (1f - fcos) - y * fsin; Value[1, 2] = z * y * (1f - fcos) + x * fsin; Value[2, 2] = fcos + (float)Math.Pow(z, 2) * (1f - fcos); }
public oDBPlanet(Point3 Pos, Point3 Dir, oDBSun Central, float mass, float Red, float Green, float Blue) { if (Central == null) { throw new Exception("Kein Zentralmassiv angegeben"); } Position.assign(Pos); Direction.assign(Dir); Center = Central; _Red = Red; _Green = Green; _Blue = Blue; Mass = mass; Size = (float)((Math.Pow(Mass, (double)(1f / 3f)) * 3f) / (4f * Math.PI)); }
private void AddPlanet() { lock (Objects) { float Mass = 1f; int ps = rnd.Next(0, 10); Mass = (float)rnd.NextDouble() * (float)Math.Pow(1, ps) * PlanetAdvanced2.UniFak; // Größe Abhängig von Basisgröße der Planeten Point3 P1Pos = RndDustPosToSun(); Point3 P1Dir = new Point3(0f, 0f, 0f); Objects.Add(new oDBPlanet(P1Pos, P1Dir, Sun, Mass, (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble())); } }
/// <summary> /// Zufällige Position bezogen auf ein Zentralobjekt /// </summary> /// <returns>beliebiger Vektor zu einer Position in der Nähe des Zentralobjektes</returns> private Point3 RndDustPosToSun() { Point3 result = new Point3(); result.x = CalcDust(); result.y = CalcDust(); result.z = CalcDust(); return result; }
/// <summary> /// eine 90° Rotationsmatrix um die z-Achse /// </summary> /// <returns></returns> private Matrix RotMatrix90z() { Point3 ZAxis = new Point3(0f, 0f, 1f); Matrix rot = new Matrix(); rot.RotMatrix(90, ZAxis); return rot; }
/// <summary> /// Zeichenmethode für das Koordinatensystem /// </summary> /// <param name="GridSize">Gittergröße für das Koordinatensystem</param> private void DrawSystem(float GridSize) { //System zeichnen Point3 cpx1 = new Point3(GridSize, 0, 0); Point3 cpx2 = new Point3(-1 * GridSize, 0, 0); Point3 cpy1 = new Point3(0, GridSize, 0); Point3 cpy2 = new Point3(0, -1 * GridSize, 0); Point3 cpz1 = new Point3(0, 0, GridSize); Point3 cpz2 = new Point3(0, 0, -1 * GridSize); float fak = 1; float i = 0; float delta = 10; Gl.glPointSize(1f); Gl.glDisable(Gl.GL_LIGHTING); Gl.glBegin(Gl.GL_LINES); { i = 0; while (!(i > GridSize)) { Gl.glColor3f(0.6f + fak * 0.3f, 0.6f + fak * 0.3f, 1f); Gl.glVertex3f(i, 0, 0); Gl.glVertex3f(i + delta, 0, 0); Gl.glColor3f(0.6f - fak * 0.3f, 0.6f - fak * 0.3f, 1f); Gl.glVertex3f(-i, 0, 0); Gl.glVertex3f(-(i + delta), 0, 0); i += delta; fak *= -1; } } Gl.glEnd(); Gl.glBegin(Gl.GL_LINES); { i = 0; while (!(i > GridSize)) { Gl.glColor3f(1f, 0.6f + fak * 0.3f, 0.6f + fak * 0.3f); Gl.glVertex3f(0, i, 0); Gl.glVertex3f(0, i + delta, 0); Gl.glColor3f(1f, 0.6f - fak * 0.3f, 0.6f - fak * 0.3f); Gl.glVertex3f(0, -i, 0); Gl.glVertex3f(0, -(i + delta), 0); i += delta; fak *= -1; } } Gl.glEnd(); Gl.glBegin(Gl.GL_LINES); { i = 0; while (!(i > GridSize)) { Gl.glColor3f(0.6f + fak * 0.3f, 1f, 0.6f + fak * 0.3f); Gl.glVertex3f(0, 0, i); Gl.glVertex3f(0, 0, i + delta); Gl.glColor3f(0.6f - fak * 0.3f, 1f, 0.6f - fak * 0.3f); Gl.glVertex3f(0, 0, -i); Gl.glVertex3f(0, 0, -(i + delta)); i += delta; fak *= -1; } } Gl.glEnd(); Gl.glEnable(Gl.GL_LIGHTING); }
public oDBSun(Point3 Pos, Point3 Dir, float size, float mass, float g) { Position = Pos; Direction = Dir; _Blue = 0.05f; _Green = 0.05f; _Red = 0.05f; Size = size; this.mass = mass; G = g; }
/// <summary> /// allgemeine Bewegungsroutine, kann überschrieben werden (für Sonnen) /// </summary> /// <param name="Objects"></param> public virtual void MoveObject(List<o2Object> Objects) { Point3 v = new Point3(0f, 0f, 0f); if (Parent == null) { foreach (o2Object o in Objects) { if (o != this) { _v(o); } } } else { _v(Parent); } Position = Position + (Direction * PlanetAdvanced2.dt); }
/// <summary> /// Constructor /// </summary> /// <param name="Pos">Position</param> /// <param name="Dir">Richtung</param> /// <param name="mass">Masse</param> /// <param name="Color">Farbarray</param> /// <param name="_Parent">Bewegung kann sich auch nur auf den Parent beziehen</param> public o2Object(Point3 Pos, Point3 Dir, float mass, float[] Color, o2Object _Parent) { Position = Pos; Direction = Dir; Mass = mass; Farbe = Color; Parent = _Parent; }
/// <summary> /// Einzelner neuer Punkt auf dem Kneul /// </summary> /// <param name="rndkn">Zufallsgenerator</param> private void NewPointKneul(Random rndkn) { Point3 StPoint = m_lPointsKneul.Last(); Point3 newPoint = new Point3(StPoint.x, StPoint.y, StPoint.z); float p = newPoint.x + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.x = p; } p = newPoint.y + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.y = p; } p = newPoint.z + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.z = p; } m_lPointsKneul.Add(newPoint); }
/// <summary> /// Bewegungsroutine für Sonne /// </summary> /// <param name="Objects"></param> public override void MoveObject(List<o2Object> Objects) { Point3 v = new Point3(0f, 0f, 0f); foreach (o2Object o in Objects) { if (o != this) { _v(o); } } //if (!lockSun) //{ // // Dämpfung, damit die Sonnen nicht abhauen. :) // Point3 Center = new Point3(); // Direction -= (Position * 0.00001f); // Direction -= (Direction - Center) * 0.001f; //} Position = Position + (Direction * PlanetAdvanced2.dt); }
/// <summary> /// eine von aussen auf die Hauptsonne zufliegende Sonne mit Planeten wird erstellt /// </summary> private void AddComingSun() { if (suncount < _Light.Length - 1) { float Massfak = (float)rnd.Next(1, 3) * 5 * PlanetAdvanced2.initSunMass; float Mass = (float)rnd.NextDouble() * Massfak; Point3 Pos = RndPosToSun(Sun, true,true); Pos = (Pos - Sun.Position) * (float)(rnd.Next(10, 20)); // Position weiter von der Sonne entfernen. Point3 Dir = new Point3(); Dir.assign(Sun.Position - Pos); // Bewegung auf die Sonne zu. Dir.x += (float)rnd.NextDouble(); // ein wenig Varianz in der Bewegung. Dir.y += (float)rnd.NextDouble(); // ein wenig Varianz in der Bewegung. Dir.z += (float)rnd.NextDouble(); // ein wenig Varianz in der Bewegung. Dir.Normalize(); // BewegungsRichtung normalisieren. Dir *= (float)((rnd.NextDouble() * 3) + 2f) * 10f; // Speed zurechnen; float[] Color = { (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble() }; suncount++; o2Sun __Sun = new o2Sun(Pos, Dir, Mass, Color, _Light[suncount]); Objects.Add(__Sun); AddPlanet(__Sun, rnd.Next(1, 9)); // 1 bis 8 Planeten auf die Umlaufbahn der neuen Sonne bringen. } }
/// <summary> /// Constructor /// </summary> /// <param name="Pos">Position</param> /// <param name="Dir">Bewegungsrichtung</param> /// <param name="mass">Masse</param> /// <param name="Color">Farbarray</param> /// <param name="light">Lichtquellenindex</param> public o2Sun(Point3 Pos, Point3 Dir, float mass, float[] Color, int light) { Mass = mass; Position.assign(Pos); Direction.assign(Dir); Farbe = Color; _light = light; }
/// <summary> /// Beschleunigung Richtung Bezugsobjekt /// </summary> /// <param name="o">Bezugsobjekt</param> /// <returns></returns> private Point3 a(o2Object o) { float distance = Point3.Distance(this.Position, o.Position); Point3 x = new Point3(); x.assign(Position - o.Position); float fak = (float)(-PlanetAdvanced2.G * o.Mass / Math.Pow(distance, 3)); return x * fak; }
/// <summary> /// Bewegungsrichtungsänderung durch Beschleunigung zum Objekt /// </summary> /// <param name="o">Bezugsobjekt</param> /// <returns>Richtungsvektor</returns> public Point3 _v(o2Object o) { Point3 _a = new Point3(); _a = a(o); return Direction = Direction + (_a * PlanetAdvanced2.dt); }
private Point3 a() { float distance = Point3.Distance(this.Position, Center.Position); Point3 x = new Point3(); x.assign(Position - Center.Position); float fak = (float)(-Center.G * Center.Mass / Math.Pow(distance, 3)); return x * fak; }
/// <summary> /// eigentliche Berechnung eines neuen Punktes /// </summary> public void NewPoint() { //Neuen Punkt errechnen Random rnd1 = new Random(m_lPoints.Count); Random rnd2 = new Random(rnd1.Next()); angle = (float)rnd2.NextDouble() * 360; angle2 = (float)rnd1.NextDouble() * 360; //Neuen Punkt hinzufuegen Point3 StPoint = new Point3(0, 0, 50); Point3 Point = new Point3(0, 0, 0); Matrix Rot = new Matrix(); Matrix Rot2 = new Matrix(); Matrix Rot3 = new Matrix(); Rot.RotMatrix(angle, new Point3(1f, 0f, 0f)); Rot2.RotMatrix(angle2, new Point3(0f, 0f, 1f)); Rot3.RotMatrix(angle, new Point3(1f, 0f, 1f)); Point = MMath.MatDotPoint(Rot, StPoint); Point = MMath.MatDotPoint(Rot2, Point); m_lPoints.Add(Point); }
private Point3 v() { Point3 _a = new Point3(); _a = a(); return Direction = Direction + (_a * dt); }
/// <summary> /// Zufällige Position bezogen auf ein Zentralobjekt /// </summary> /// <returns>beliebiger Vektor zu einer Position in der Nähe des Zentralobjektes</returns> private Point3 RndDustPosToSun() { Point3 result = new Point3(); result.x = CalcDust(); result.y = CalcDust(); result.z = 0f; // result.z = fak() * (float)rnd.NextDouble() * 100f; return result; }
/// <summary> /// Initialisierung der Funktion /// </summary> private void initFunction() { double _xmin = fmin; double _xmax = fmax; double _ymin = fmin; double _ymax = fmax; int ix = -1; int iy = -1; m_lPointsFunction.Clear(); m_lPointsFunctionLines.Clear(); for (double x = _xmin; x <= _xmax; x += step) { ix += 1; for (double y = _ymin; y <= _ymax; y += step) { iy += 1; double z = solvef(x, y); Point3 a = new Point3((float)x, (float)y, (float)z); z = solvef(x + step, y); Point3 b = new Point3((float)(x + step), (float)y, (float)z); z = solvef(x, y + step); Point3 c = new Point3((float)(x), (float)(y + step), (float)z); z = solvef(x + step, y + step); Point3 d = new Point3((float)(x + step), (float)(y + step), (float)z); m_lPointsFunction.Add(new Square(a, c, d, b)); if (ix % 5 == 0 && iy % 5 == 0) { m_lPointsFunctionLines.Add(new Square(a, c, d, b)); } } } }
/// <summary> /// Constructor für Schuss /// </summary> /// <param name="cam">Kameraobjekt dient zur ermittlung der Position und Ausrichtung</param> /// <param name="Dir">Richtung in die der Schuss fliegen soll (wird intern normiert)</param> /// <param name="Red">Rotanteil in der Farbe</param> /// <param name="Green">Grünanteil in der Farbe</param> /// <param name="Blue">Blauanteil in der Farbe</param> /// <param name="Speed">Bewegungsgeschwindigkeit</param> public Shot(Camera cam, Point3 Dir, float Red, float Green, float Blue, float Speed) { // Richtung gleich normieren float n = (float)Math.Sqrt(Math.Pow(Dir.x, 2) + Math.Pow(Dir.y, 2) + Math.Pow(Dir.z, 2)); _Dir.x = Dir.x / n; _Dir.y = Dir.y / n; _Dir.z = Dir.z / n; _Pos.x = __InitPos.x = -cam.X; _Pos.y = __InitPos.y = -cam.Y; _Pos.z = __InitPos.z = -cam.Z; _AngleX = cam.angleX; _AngleZ = cam.angleZ; _Red = Red; _Green = Green; _Blue = Blue; _Speed = Speed; _Birthtime = DateTime.Now; }
/// <summary> /// einzelner neuer Punkt auf dem Kneul /// </summary> /// <param name="rndkn">Zufallsgenerator</param> /// <param name="kneulspeed">Länge des Zaubers</param> private void NewPointZauber(Random rndkn, int kneulspeed) { Point3 StPoint = m_lPointsZauber.Last(); Point3 newPoint = new Point3(StPoint.x, StPoint.y, StPoint.z); float p = newPoint.x + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.x = p; } p = newPoint.y + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.y = p; } p = newPoint.z + (float)rndkn.NextDouble() - 0.5f; if (!(p >= 50) && !(p <= -50)) { newPoint.z = p; } m_lPointsZauber.Add(newPoint); while (m_lPointsZauber.Count > (100 * kneulspeed)) { m_lPointsZauber.RemoveAt(0); } }
/// <summary> /// Initialisiertung Tangentialebene in P=(x0,y0,z0) /// </summary> private void initFunctionTangent() { double dif = 4f; m_lPointsFunctionTangent.Clear(); double x = x0 - dif; // links unten double y = y0 - dif; double z = tangentPlane(x, y); Point3 lu = new Point3((float)x, (float)y, (float)z); x = x0 + dif; // rechts unten y = y0 - dif; z = tangentPlane(x, y); Point3 ru = new Point3((float)(x), (float)y, (float)z); x = x0 - dif; // links oben y = y0 + dif; z = tangentPlane(x, y); Point3 lo = new Point3((float)(x), (float)(y), (float)z); // rechts oben Point3 ro = new Point3((float)(x), (float)(y), (float)z); Point3 lr = new Point3(lu.x - ru.x, lu.y - ru.y, lu.z - ru.z); Point3 ou = new Point3(lo.x - lu.x, lo.y - lu.y, lo.z - lu.z); lr.Normalize(); ou.Normalize(); z0 = (float)solvef(x0, y0); Point3 X0 = new Point3(x0, y0, z0); lr *= dif / 2; ou *= dif / 2; lu.assign(X0); lu -= lr; lu -= ou; lo.assign(X0); lo -= lr; lo += ou; ro.assign(X0); ro += lr; ro += ou; ru.assign(X0); ru += lr; ru -= ou; m_lPointsFunctionTangent.Add(new Square(lu, lo, ro, ru)); }
/// <summary> /// Fügt einem Zentralobjekt untergeordnete es umkreisende Objekte hinzu /// </summary> /// <param name="cnt">Anzahl der das Zentralobjekt umkreisenden Objekte</param> private void AddDust(int cnt) { for (int i = 0; i < cnt; i++) { float Mass = 1f; int ps = rnd.Next(28, 30); Mass = (float)rnd.NextDouble() * (float)Math.Pow(10, ps) * PlanetAdvanced2.UniFak; // Größe Abhängig von Basisgröße der Planeten Point3 Pos = RndDustPosToSun(); // Position soll relativ zum Ursprung sein Point3 Dir = new Point3(); float[] Color = { (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble() }; // Farbe ist zufällig o2Object p = new o2Object(Pos, Dir, Mass, Color,null); Objects.Add(p); } }
public oSun(Point3 Pos, Point3 Dir, float size, float mass, float g) { Position = Pos; Direction = Dir; _Blue = 0.9f; _Green = 0.9f; _Red = 1f; Size = size; Mass = mass; G = g; }
/// <summary> /// Zufällige Position bezogen auf ein Zentralobjekt /// </summary> /// <param name="_Sun">Zentralobjekt</param> /// <param name="isSun">Ist neues Objekt eine Sonne?</param> /// <param name="SunIsParent">Ist die Hauptsonne das Zentralobjekt?</param> /// <returns>beliebiger Vektor zu einer Position in der Nähe des Zentralobjektes</returns> private Point3 RndPosToSun(o2Object _Sun, bool isSun , bool SunIsParent) { Point3 result = new Point3(); result.x = _Sun.Position.x + Calc(_Sun, isSun, SunIsParent); result.y = _Sun.Position.y + Calc(_Sun, isSun, SunIsParent); result.z = _Sun.Position.z + fak() * (float)rnd.NextDouble() * 100f; return result; }
public override void Init() { Point3 SunPos = new Point3(); Point3 SunDir = new Point3(); Sun = new oSun(SunPos, SunDir, 20f, 100f, 9.81f); Objects.Add(Sun); }
/// <summary> /// eine Simulationsperiode /// </summary> private void ThreadTick() { float distance; float ri; float rj; o2Object oi; o2Object oj; try { #region Bewegung foreach (o2Object o in Objects) { o.MoveObject(Objects); if (showTrace) { o.Trace(); } } #endregion } catch { } try // Wegen Threading kommt es gern zu Fehlern beim Entfernen von Objekten. Das wird hier abgefangen. { // ist unsauber und langsamer, ich weiß. #region Kollision // Kollisionsabfrage Schwereres Objekt bekommt Masse von leichterem Objekt // und der Impuls des kleineren wird auf den größeren gerechnet. // Sonne wird nicht zerstört, da sie Lichtquelle ist. for (int i = 0; i < Objects.Count - 1; i++) { for (int j = i + 1; j < Objects.Count; j++) { oi = Objects[i]; oj = Objects[j]; distance = Point3.Distance(oi.Position, oj.Position); Point3 impulse = new Point3(); ri = oi.Size; rj = oj.Size; if (ri + rj > distance) // Objekte kollidieren ( Summe der Radien > Abstand ) { impulse = (oi.Direction * oi.Mass) + (oj.Direction * oj.Mass); if (Objects[i] == Sun) // erstes Objekt ist die HauptSonne - Hauptsonne soll bleiben. { Sun.Mass += oj.Mass; Sun.Direction = impulse / Sun.Mass; Objects.Remove(oj); ConvertPlanet2Sun(oi); break; } else { if (Objects[j] == Sun) // zweites Objekt ist die Hauptsonne - Hauptsonne soll bleiben { Sun.Mass += oi.Mass; Sun.Direction = impulse / Sun.Mass; Objects.Remove(oi); ConvertPlanet2Sun(oj); break; } else // Kein Objekt ist die Hauptsonne. { if (oi.Mass > oj.Mass) { oi.Mass += oj.Mass; oi.Direction = impulse / oi.Mass; Objects.Remove(oj); ConvertPlanet2Sun(oi); break; } else { oj.Mass += oi.Mass; oj.Direction = impulse / oj.Mass; Objects.Remove(oi); ConvertPlanet2Sun(oj); break; } } } } } } #endregion } catch { } try // Wegen Threading kommt es gern zu Fehlern beim Entfernen von Objekten. Das wird hier abgefangen. { // ist unsauber und langsamer, ich weiß. #region zu weit vom Ursprung entfernte Objekte entfernen for (int i = Objects.Count - 1; i >= 0; i--) { o2Object o = Objects[i]; distance = Point3.Distance(new Point3(), o.Position); if (distance > 1000000) { if (o == Sun) { Sun.Direction = new Point3(); Sun.Position = new Point3(); } else { Objects.Remove(o); } } } #endregion } catch (Exception) { } if (Sun != null && centered) { resetSun(); } }
private void AddPlanet() { lock (Objects) { Point3 P1Pos = new Point3(0f, 0f, 0f); int fak = rnd.Next(2) - 1 < 0 ? -1 : 1; P1Pos.x = fak * (float)rnd.Next(100, 100 + (int)Sun.Size); fak = rnd.Next(2) - 1 < 0 ? -1 : 1; P1Pos.y = fak * (float)rnd.Next(100, 100 + (int)Sun.Size); Point3 P1Dir = new Point3(0f, 0f, 0f); Matrix rot = new Matrix(); Point3 ZAxis = new Point3(0f, 0f, 1f); rot.RotMatrix(90, ZAxis); P1Dir = MM.MatDotPoint(rot, P1Pos); P1Dir.Normalize(); P1Dir = P1Dir * rnd.NextDouble() * 3f; Objects.Add(new oPlanet(P1Pos, P1Dir, Sun, ((float)rnd.NextDouble() * 3f) + 2f, (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble())); } }