/// <summary> /// reverse transformation. /// </summary> public override Vec3 Transform(Vec3 input) { Vec3 p1 = input.Diff(_camera); double dp = p1.Norm; double fac = dp / d; Vec3 p1_p = p1.Mult(fac); return (p1_p.Sum(_camera)); }
/// <summary> /// Reversed reverse transformation. /// </summary> public Vec3 ReverseTransform(Vec3 input) { Vec3 transformedCamera = Transform(_camera); Vec3 tempVec = input.Diff(transformedCamera); double l = tempVec.Norm; double dt = Math.Sqrt(l * d); tempVec.Normalize(); tempVec = tempVec.Mult(dt); return (tempVec.Sum(transformedCamera)); }
/// <summary> /// Activate zooming. /// </summary> private void SetZoom() { if (_iterate == null) { return; } try { // compute Min and Max double minX = double.MaxValue; double minY = double.MaxValue; double minZ = double.MaxValue; double maxX = double.MinValue; double maxY = double.MinValue; double maxZ = double.MinValue; if (_zoomX2 - _zoomX1 < 4) { _zoomX1 -= _width / 10; _zoomX2 += _width / 10; if (_zoomX1 < 0) { _zoomX1 = 0; } if (_zoomX2 >= _width) { _zoomX2 = _width - 1; } _zoomY1 -= _height / 10; _zoomY2 += _height / 10; if (_zoomY1 < 0) { _zoomY1 = 0; } if (_zoomY2 >= _height) { _zoomY2 = _height - 1; } } // iter.PictureData.Points double x, y, z; int noOfPixelsFound = 0; for (int i = _zoomX1; i <= _zoomX2; i++) { for (int j = _zoomY1; j <= _zoomY2; j++) { if (_iterate.GraphicInfo.PointInfo[i, j] != null) { x = _iterate.GraphicInfo.PointInfo[i, j].i; y = _iterate.GraphicInfo.PointInfo[i, j].j; z = _iterate.GraphicInfo.PointInfo[i, j].k; Geometry.Vec3 trans2 = _iterate.LastUsedFormulas.GetTransform(x, y, z); x = trans2.X; y = trans2.Y; z = trans2.Z; if (minX > x) { minX = x; } if (maxX < x) { maxX = x; } if (minY > y) { minY = y; } if (maxY < y) { maxY = y; } if (minZ > z) { minZ = z; } if (maxZ < z) { maxZ = z; } noOfPixelsFound++; } } } if (noOfPixelsFound < 5) { System.Diagnostics.Debug.WriteLine("No Pixel found in zoom."); return; } // Set parameters: _paras.Parameter.start_tupel.x = minX; _paras.Parameter.start_tupel.y = minY; _paras.Parameter.start_tupel.z = minZ; _paras.Parameter.end_tupel.x = maxX; _paras.Parameter.end_tupel.y = maxY; _paras.Parameter.end_tupel.z = maxZ; _paras.Parameter.TransferToParameterDict(); _paras.UpdateFromData(); ParameterInput.MainParameterInput.DrawSmallPreview(); } catch (System.Exception ex) { // Array out of bounds System.Diagnostics.Debug.WriteLine(ex.ToString()); } }
protected virtual Vec3 GetRgbAt(int x, int y) { Vec3 retVal = new Vec3(1, 0, 0); // rot return retVal; }
/// <summary> /// Compute field of view. /// </summary> protected void SmoothPlane() { double fieldOfViewStart = minFieldOfView; ydGlobal = (areaDeph) / ((double)(Math.Max(pData.Width, pData.Height))); rgbSmoothPlane1 = new Vec3[pData.Width, pData.Height]; rgbSmoothPlane2 = new Vec3[pData.Width, pData.Height]; int intRange = 3; for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { rgbSmoothPlane2[i, j] = rgbPlane[i, j]; } } if (ambientIntensity == 0) { // No field of view defined: return; } // starts with rgbSmoothPlane2 Vec3[,] currentPlane = rgbSmoothPlane2; Vec3[,] nextPlane = rgbSmoothPlane1; // contain the result colors Vec3[,] resultPlane = rgbSmoothPlane1; double mainDeph1 = areaDeph; for (int m = 0; m < ambientIntensity; m++) { if (_stopRequest) return; for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { double neighborsFound = 0; PixelInfo pInfo = pData.Points[i, j]; Vec3 nColor = new Vec3(); double ydNormalized = GetAmbientValue(smoothDeph2[i, j]); ydNormalized = Math.Sqrt(ydNormalized); intRange = 1; if (intRange == 0) { nColor = currentPlane[i, j]; neighborsFound = 1; } double sumColor = 0; // if(pData.Points[i, j]!=null) { if (true) { for (int k = -intRange; k <= intRange; k++) { for (int l = -intRange; l <= intRange; l++) { // Center Pixel is also allowed // if (k != 0 || l != 0) { int posX = i + k; int posY = j + l; if (posX >= 0 && posX < pData.Width && posY >= 0 && posY < pData.Height) { Vec3 nColor1 = new Vec3(); double ylocalDiff = smoothDeph1[i, j] - smoothDeph1[posX, posY]; if (true) // if ( (ylocalDiff > 0) ||(i==posX && j==posY)) // if ((ylocalDiff < 0) || (i == posX && j == posY)) // if(false) { //double range = (k * k + l * l) / (intRange * intRange); int range = (k * k + l * l); double mult = 1; if (range == 0) { // mult = 0.6; mult = ydNormalized * 0.3; //mult = 0.2; } if (range == 1) { //mult = 0.25; mult = (1.0 - ydNormalized) * 0.4; //mult = 0.45; } if (range == 2) { //mult=0.15; mult = (1.0 - ydNormalized) * 0.3; //mult = 0.35; } // mult += 0.00001; PixelInfo pInfo2 = pData.Points[posX, posY]; double amount = 1; if (pInfo != null && pInfo2 != null) { double dist = pInfo.Coord.Dist(pInfo2.Coord); double dGlobal = maxPoint.Dist(minPoint); dGlobal /= 1500; if (dist < dGlobal) amount = 1.0; else // else if (dist > dGlobal && dist < 10.0 * dGlobal) amount = 1.0 - (dGlobal / dist) / 10.0; // else // amount = 0.0; } mult *= amount; // mult *= 1.0/ydNormalized; sumColor += mult; Vec3 currentColor = currentPlane[posX, posY]; nColor1.X = currentColor.X; nColor1.Y = currentColor.Y; nColor1.Z = currentColor.Z; nColor1 = nColor1.Mult(mult); // Scaling; nColor.Add(nColor1); neighborsFound++; } } } } } if (neighborsFound > 1) { nColor = nColor.Mult(1 / sumColor); } else { nColor = currentPlane[i, j]; } nextPlane[i, j] = nColor; } } resultPlane = nextPlane; nextPlane = currentPlane; currentPlane = resultPlane; } for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { rgbPlane[i, j] = resultPlane[i, j]; } } rgbSmoothPlane1 = null; rgbSmoothPlane2 = null; return; }
/// <summary> /// Get the color information of the bitmap at (x,y) /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> protected Vec3 GetRgb(int x, int y) { Vec3 retVal = new Vec3(0, 0, 1); // blau PixelInfo pInfo = pData.Points[x, y]; if (pInfo == null) { return new Vec3(backColorRed, backColorGreen, backColorBlue); } Vec3 light = new Vec3(0, 0, 0); Vec3 normal = null; normal = normalesSmooth1[x, y]; if (normal == null) { normal = pInfo.Normal; } // Testweise original Normale verwenden // normal = pInfo.Normal; // TODO: Obiges auskommentieren if (normal == null) return new Vec3(0, 0, 0); // tempcoord2 enthält die umgerechnete Oberflächennormale. double tfac = 1000; Vec3 coord = formula.GetTransform(pInfo.Coord.X, pInfo.Coord.Y, pInfo.Coord.Z); normal.Normalize(); Vec3 tempcoord2 = formula.GetTransform(pInfo.Coord.X + tfac * normal.X, pInfo.Coord.Y + tfac * normal.Y, pInfo.Coord.Z + tfac * normal.Z); tempcoord2.X -= coord.X; tempcoord2.Y -= coord.Y; tempcoord2.Z -= coord.Z; // Normalize: tempcoord2.Normalize(); // debug only tempcoord2 = normal; if (pInfo.Normal != null) { light = GetLight(tempcoord2); if (sharpShadow != null) { light = light.Mult(1 - sharpShadow[x, y]); } } retVal.X = light.X; retVal.Y = light.Y; retVal.Z = light.Z; double d1 = maxY - minY; double d2 = pData.Width + pData.Height; double d3 = d1 / d2; retVal.X = (lightIntensity * retVal.X + (1 - lightIntensity) * (1 - shadowPlane[x, y])); retVal.Y = (lightIntensity * retVal.Y + (1 - lightIntensity) * (1 - shadowPlane[x, y])); retVal.Z = (lightIntensity * retVal.Z + (1 - lightIntensity) * (1 - shadowPlane[x, y])); if (retVal.X < 0) retVal.X = 0; if (retVal.Y < 0) retVal.Y = 0; if (retVal.Z < 0) retVal.Z = 0; if (retVal.X > 1) retVal.X = 1; if (retVal.Y > 1) retVal.Y = 1; if (retVal.Z > 1) retVal.Z = 1; double brightLightLevel = ParameterDict.Current.GetDouble("Renderer.BrightLightLevel"); if (brightLightLevel > 0) { retVal.X = (1 - brightLightLevel) * retVal.X + brightLightLevel * light.X * (1 - shadowPlane[x, y]); retVal.Y = (1 - brightLightLevel) * retVal.Y + brightLightLevel * light.Y * (1 - shadowPlane[x, y]); retVal.Z = (1 - brightLightLevel) * retVal.Z + brightLightLevel * light.Z * (1 - shadowPlane[x, y]); } if (retVal.X < 0) retVal.X = 0; if (retVal.Y < 0) retVal.Y = 0; if (retVal.Z < 0) retVal.Z = 0; if (retVal.X > 1) retVal.X = 1; if (retVal.Y > 1) retVal.Y = 1; if (retVal.Z > 1) retVal.Z = 1; // Add surface color bool useAdditionalColorinfo = true; if (colorIntensity <= 0) useAdditionalColorinfo = false; if (useAdditionalColorinfo && ((pInfo.IsInside && _colorInside) || (!pInfo.IsInside && _colorOutside))) { if (pInfo != null && pInfo.AdditionalInfo != null) { // Normalise; double r1 = colorFactorRed * Math.Pow(pInfo.AdditionalInfo.red, colorIntensity); double g1 = colorFactorGreen * Math.Pow(pInfo.AdditionalInfo.green, colorIntensity); double b1 = colorFactorBlue * Math.Pow(pInfo.AdditionalInfo.blue, colorIntensity); if (r1 < 0) r1 = -r1; if (g1 < 0) g1 = -g1; if (b1 < 0) b1 = -b1; // Normalize: double norm = Math.Sqrt(r1 * r1 + g1 * g1 + b1 * b1)/Math.Sqrt(2.5); r1 = r1 / norm; g1 = g1 / norm; b1 = b1 / norm; for (int i = 0; i < 5; i++) { if (r1 > 1) { b1 += (r1 - 1) / 2.0; g1 += (r1 - 1) / 2.0; r1 = 1; } if (b1 > 1) { r1 += (b1 - 1) / 2.0; g1 += (b1 - 1) / 2.0; b1 = 1; } if (g1 > 1) { r1 += (g1 - 1) / 2.0; b1 += (g1 - 1) / 2.0; g1 = 1; } } if (r1 > 1) r1 = 1; if (b1 > 1) b1 = 1; if (g1 > 1) g1 = 1; if (colorGreyness > 0) { r1 = colorGreyness + (1 - colorGreyness) * r1; g1 = colorGreyness + (1 - colorGreyness) * g1; b1 = colorGreyness + (1 - colorGreyness) * b1; } if (r1 > 1) r1 = 1; if (b1 > 1) b1 = 1; if (g1 > 1) g1 = 1; if (norm != 0) { switch (rgbType) { case 1: retVal.X *= r1; retVal.Y *= g1; retVal.Z *= b1; break; case 2: retVal.X *= r1; retVal.Y *= b1; retVal.Z *= g1; break; case 3: retVal.X *= g1; retVal.Y *= r1; retVal.Z *= b1; break; case 4: retVal.X *= g1; retVal.Y *= b1; retVal.Z *= r1; break; case 5: retVal.X *= b1; retVal.Y *= r1; retVal.Z *= g1; break; case 6: retVal.X *= b1; retVal.Y *= g1; retVal.Z *= r1; break; default: retVal.X *= r1; retVal.Y *= g1; retVal.Z *= b1; break; } } } } if (contrast != 1) { retVal.X = Math.Pow(retVal.X, contrast); retVal.Y = Math.Pow(retVal.Y, contrast); retVal.Z = Math.Pow(retVal.Z, contrast); } if (brightness > 1) { retVal.X *= brightness; retVal.Y *= brightness; retVal.Z *= brightness; } if (retVal.X < 0) retVal.X = 0; if (retVal.X > 1) retVal.X = 1; if (retVal.Y < 0) retVal.Y = 0; if (retVal.Z < 0) retVal.Z = 0; if (retVal.Y > 1) retVal.Y = 1; if (retVal.Z > 1) retVal.Z = 1; if (pInfo != null && pInfo.AdditionalInfo != null) { pInfo.AdditionalInfo.red2 = retVal.X; pInfo.AdditionalInfo.green2 = retVal.Y; pInfo.AdditionalInfo.blue2 = retVal.Z; } return retVal; }
/// <summary> /// calculates the effect of this rotation on a point /// the new point is given by=q * P1 * q' /// this version does not alter P1 but returns the result. /// /// for theory see: /// http://www.martinb.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm /// </summary> /// <param name="point">point to be transformed</param> /// <returns>translated point</returns> public Vec3 getTransform(Vec3 p1) { double wh = Angle; double xh = X; double yh = Y; double zh = Z; double s = Math.Sin(Angle / 2); xh = X * s; yh = Y * s; zh = Z * s; wh = Math.Cos(Angle / 2); Vec3 p2 = new Vec3(0, 0, 0); p2.X = (double)(wh * wh * p1.X + 2 * yh * wh * p1.Z - 2 * zh * wh * p1.Y + xh * xh * p1.X + 2 * yh * xh * p1.Y + 2 * zh * xh * p1.Z - zh * zh * p1.X - yh * yh * p1.X); p2.Y = (double)(2 * xh * yh * p1.X + yh * yh * p1.Y + 2 * zh * yh * p1.Z + 2 * wh * zh * p1.X - zh * zh * p1.Y + wh * wh * p1.Y - 2 * xh * wh * p1.Z - xh * xh * p1.Y); p2.Z = (double)(2 * xh * zh * p1.X + 2 * yh * zh * p1.Y + zh * zh * p1.Z - 2 * wh * yh * p1.X - yh * yh * p1.Z + 2 * wh * xh * p1.Y - xh * xh * p1.Z + wh * wh * p1.Z); return p2; }
public Projection(Vec3 camera, Vec3 viewPoint) { this._camera = camera; this._viewPoint = viewPoint; d = camera.Dist(viewPoint); }
/// <summary> /// Return distance to other point. /// </summary> public double Dist(Vec3 other) { return Diff(other).Norm; }
/// <summary> /// Return path to other point as vector. /// </summary> public Vec3 Diff(Vec3 other) { return (new Vec3(this.X - other.X, Y - other.Y, Z - other.Z)); }
/// <summary> /// Add point other. /// </summary> public void Add(Vec3 other) { X += other.X; Y += other.Y; Z += other.Z; }
public Vec3(Vec3 other) { this.X = other.X; this.Y = other.Y; this.Z = other.Z; }
/// <summary> /// + Operator /// </summary> public Vec3 Sum(Vec3 other) { return new Vec3(X + other.X, Y + other.Y, Z + other.Z); }
/// <summary> /// Subtract componentwise. /// </summary> public void Subtract(Vec3 other) { X -= other.X; Y -= other.Y; Z -= other.Z; }
/// <summary> /// Set centerDiffX, centerDiffY and centerDiffZ. /// </summary> public void UpdateCenterDiff() { double centerX = ParameterDict.Current.GetDouble("Scene.CenterX"); double centerY = ParameterDict.Current.GetDouble("Scene.CenterY"); double centerZ = ParameterDict.Current.GetDouble("Scene.CenterZ"); //Rotation rotView = null; double centerXChange = centerX + 1; double centerYChange = centerY + 1; double centerZChange = centerZ + 1; // For Zerotest double minDoubleVal = 0.0000000000000001; // This does not work for angle combinations: Rotation rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffX = rotView.TransformForNavigation(new Vec3(1, 0, 0)); rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffY = rotView.TransformForNavigation(new Vec3(0, -1, 0)); rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffZ = rotView.TransformForNavigation(new Vec3(0, 0, -1)); // Set 0-Entries if (centerDiffX.X > -minDoubleVal && centerDiffX.X < minDoubleVal) centerDiffX.X = 0; if (centerDiffX.Y > -minDoubleVal && centerDiffX.Y < minDoubleVal) centerDiffX.Y = 0; if (centerDiffX.Z > -minDoubleVal && centerDiffX.Z < minDoubleVal) centerDiffX.Z = 0; if (centerDiffY.X > -minDoubleVal && centerDiffY.X < minDoubleVal) centerDiffY.X = 0; if (centerDiffY.Y > -minDoubleVal && centerDiffY.Y < minDoubleVal) centerDiffY.Y = 0; if (centerDiffY.Z > -minDoubleVal && centerDiffY.Z < minDoubleVal) centerDiffY.Z = 0; if (centerDiffZ.X > -minDoubleVal && centerDiffZ.X < minDoubleVal) centerDiffZ.X = 0; if (centerDiffZ.Y > -minDoubleVal && centerDiffZ.Y < minDoubleVal) centerDiffZ.Y = 0; if (centerDiffZ.Z > -minDoubleVal && centerDiffZ.Z < minDoubleVal) centerDiffZ.Z = 0; }
/// <summary> /// Set centerDiffX, centerDiffY and centerDiffZ. /// </summary> public void UpdateCenterDiff() { // For Zerotest double minDoubleVal = 0.0000000000000001; Rotation rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffX = rotView.TransformForNavigation(new Vec3(1, 0, 0)); rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffY = rotView.TransformForNavigation(new Vec3(0, -1, 0)); rotView = new Rotation(); rotView.Init(0, 0, 0, -ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); centerDiffZ = rotView.TransformForNavigation(new Vec3(0, 0, -1)); // Set 0-Entries if (centerDiffX.X > -minDoubleVal && centerDiffX.X < minDoubleVal) centerDiffX.X = 0; if (centerDiffX.Y > -minDoubleVal && centerDiffX.Y < minDoubleVal) centerDiffX.Y = 0; if (centerDiffX.Z > -minDoubleVal && centerDiffX.Z < minDoubleVal) centerDiffX.Z = 0; if (centerDiffY.X > -minDoubleVal && centerDiffY.X < minDoubleVal) centerDiffY.X = 0; if (centerDiffY.Y > -minDoubleVal && centerDiffY.Y < minDoubleVal) centerDiffY.Y = 0; if (centerDiffY.Z > -minDoubleVal && centerDiffY.Z < minDoubleVal) centerDiffY.Z = 0; if (centerDiffZ.X > -minDoubleVal && centerDiffZ.X < minDoubleVal) centerDiffZ.X = 0; if (centerDiffZ.Y > -minDoubleVal && centerDiffZ.Y < minDoubleVal) centerDiffZ.Y = 0; if (centerDiffZ.Z > -minDoubleVal && centerDiffZ.Z < minDoubleVal) centerDiffZ.Z = 0; }
/// <summary> /// Solve the equation system a*pp1+b*pp2+c*pp3=pp0 /// </summary> Vec3 SolveEqusyst(Vec3 pp0, Vec3 pp1, Vec3 pp2, Vec3 pp3) { double s = 0, t = 0, u = 0; // Solve: // a1*s+a2*t+a3*u=a0; // b1*s+b2*t+b3*u=b0; // c1*s+c2*t+c3*u=c0; double a0 = pp0.X, b0 = pp0.Y, c0 = pp0.Z; double a1 = pp1.X, b1 = pp1.Y, c1 = pp1.Z; double a2 = pp2.X, b2 = pp2.Y, c2 = pp2.Z; double a3 = pp3.X, b3 = pp3.Y, c3 = pp3.Z; // Gauss transformation to get: // x11*s + x12*t + x13*u = x14 // x22*t + x23*u = x24 // x33*u = x34 double x11, x12, x13, x14; double x22, x23, x24; double x33, x34; if (a1 != 0) { x11 = a1; x12 = a2; x13 = a3; x14 = a0; if (a1 * b2 - b1 * a2 != 0) { x22 = a1 * b2 - b1 * a2; x23 = a1 * b3 - b1 * a3; x24 = a1 * b0 - b1 * a0; x33 = (a1 * b2 - b1 * a2) * (a1 * c3 - c1 * a3) - (a1 * c2 - c1 * a2) * (a1 * b3 - b1 * a3); x34 = (a1 * b2 - b1 * a2) * (a1 * c0 - c1 * a0) - (a1 * c2 - c1 * a2) * (a1 * b0 - b1 * a0); } else { // Dritte mit zweiter Zeile tauschen x22 = a1 * c2 - c1 * a2; x23 = a1 * c3 - c1 * a3; x24 = a1 * c0 - c1 * a0; x33 = a1 * b3 - b1 * a3; x34 = a1 * b0 - b1 * a0; } } else { if (b1 != 0) { // Erste mit zweiter Zeile vertauschen x11 = b1; x12 = b2; x13 = b3; x14 = b0; if (a2 != 0) { x22 = a2; x23 = a3; x24 = a0; x33 = a2 * b1 * c3 - a2 * c1 * b3 - a3 * b1 * c2 + a3 * c1 * b2; x34 = a2 * b1 * c0 - a2 * c1 * b0 - a0 * b1 * c2 + a0 * c1 * b2; } else { // Dritte mit zweiter Zeile vertauschen x22 = b1 * c2 - c1 * b2; x23 = b1 * c3 - c1 * b3; x24 = b1 * c0 - c1 * b0; x33 = a3; x34 = a0; } } else { // Erste mit dritter Zeile vertauschen x11 = c1; x12 = c2; x13 = c3; x14 = c0; if (a2 != 0) { x22 = a2; x23 = a3; x24 = a0; x33 = a2 * b3 - b2 * a3; x34 = a2 * b0 - b2 * a0; } else { // Zweite mit dritter Zeile vertauschen x22 = b2; x23 = b3; x24 = b0; x33 = a3; x34 = a0; } } } if (x33 == 0) { if (x34 != 0) { return new Vec3(0, 0, 0); } else { u = 0; // u beliebig wählbar, bei u=0 liegt Punkt auf der Fläche if (x22 == 0) t = 1; // t beliebig wählbar else t = x24 / x22; if (x11 == 0) s = 1; // s beliebig wählbar else s = (x14 - x12 * t) / x11; } } else { // x33!=0 u = x34 / x33; if (x22 == 0) t = 1; // t beliebig wählbar else t = (x24 - x23 * u) / x22; if (x11 == 0) s = 1; // s beliebig wählbar else s = (x14 - x12 * t - x13 * u) / x11; } return new Vec3(s, t, u); }
/// <summary> /// Im Gegensatz zu klasischen Funktion Winkel wird hier von vorn gerechnet, /// die isometrische Ansicht entfällt. /// </summary> /// <param name="zykl"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="zz"></param> /// <param name="xd"></param> /// <param name="yd"></param> /// <param name="zd"></param> /// <param name="zzd"></param> /// <param name="wix"></param> /// <param name="wiy"></param> /// <param name="wiz"></param> /// <param name="jx"></param> /// <param name="jy"></param> /// <param name="jz"></param> /// <param name="jzz"></param> /// <param name="formula"></param> /// <param name="use4Points">Hier wird unterschieden, ob nur dieser Punkt, oder auch seine Nachbarpixel /// betrachtet werden.</param> /// <returns></returns> public double WinkelPerspective(long zykl, double x, double y, double z, double zz, double xd, double yd, double zd, double zzd, double wix, double wiy, double wiz, double jx, double jy, double jz, double jzz, int formula, bool invers, int pixelX, int pixelY, bool use4Points) { if (zd == 0) { Console.WriteLine("Error in WinkelPerspective: zd==0"); return 0; } PixelInfo[] borderPoints = new PixelInfo[4]; double m = 0; double xv = 0, yv = 0, zv = 0, winkel = 0, yn = 0, diff = 0; double xn = 0, zn = 0, zzn = 0, xm = 0, ym = 0, zm = 0, zzm = 0; double ox = 0, oy = 0, oz = 0, rx = 0, ry = 0, rz = 0; double[] tief = new double[5]; double[] xpos = new double[5]; double[] ypos = new double[5]; // Die ungenaue Variante von tief[] double[] zpos = new double[5]; double startwert = 0; int k = 0; double wert = 0; int pu = 0; double distance = 0.09; // Testweise verkleinert: // distance = 0.06; double xDistance = distance * 6.0; double zDistance = distance * 6.0; // debug only // zDistance = distance * 2.0; // Eventuell während der Berechnung entstehende Zusatzinfos für alle 4 Punkte. AdditionalPointInfo[] pinfoSet = null; if (mInternFormula != null && mInternFormula.additionalPointInfo != null) { pinfoSet = new AdditionalPointInfo[5]; } for (k = 4; k >= 0; k--) { switch (k) { case 2: /* oben */ xn = x; yn = y; zn = z - zDistance * zd; zzn = zz - zDistance * zzd; break; case 1: /* rechts */ xn = x + xDistance * xd; yn = y; zn = z; zzn = zz; break; case 0: /* unten */ xn = x; yn = y; zn = z + zDistance * zd; zzn = zz + zDistance * zzd; break; case 3: /* links */ xn = x - xDistance * xd; yn = y; zn = z; zzn = zz; break; case 4: /* mitte */ xn = x; yn = y; zn = z; zzn = zz; break; } xpos[k] = xn; ypos[k] = yn; zpos[k] = zn; if (Rechne(xn, yn, zn, zzn, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { for (m = 0; m >= -4.0; m -= 0.2) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (!(Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) break; } } else { for (m = 0; m <= 4.0; m += 0.2) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { m -= 0.2; break; } } } if ((m > -3.9) && (m < 3.9)) { startwert = m + 0.2; diff = 0.1; while (diff >= 0.00001) { m = startwert - diff; zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (0L == Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers)) startwert = m + diff; else startwert = m; diff /= 2.0; } tief[k] = m; } else { // Fast Kopie der obigen Formeln if (Rechne(xn, yn, zn, zzn, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { for (m = 0; m >= -8.0; m -= 0.02) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (!(Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) { if (!(Rechne(xm, ym + yd / 2.0, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) { break; } else { // break; // Staubzähler erhöhen } } } } else { for (m = 0; m <= 8.0; m += 0.02) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { if (Rechne(xm, ym + yd / 2.0, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { m -= 0.02; break; } else { // Staubzähler erhöhen //m -= 0.02; //break; } } } } if ((m > -7.9) && (m < 7.9)) { startwert = m + 0.02; diff = 0.01; while (diff >= 0.00001) { m = startwert - diff; zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (0L == Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers)) startwert = m + diff; else startwert = m; diff /= 2.0; } tief[k] = m; } else { tief[k] = 20; } // Ende: Fast Kopie der obigen Formeln } if (pinfoSet != null) { pinfoSet[k] = new AdditionalPointInfo(mInternFormula.additionalPointInfo); } } // Die Normalen der 4 Randpunkte Vec3[] normals = new Vec3[4]; for (k = 0; k < 4; k++) { pu = k + 1; if (k == 3) pu = 0; /* Die drei Punkte entsprechen tief[4] tief[k] und tief[pu] */ /* Zuerst wird tief abgezogen */ if ((tief[k] < 19) && (tief[pu] < 19) && tief[4] < 19) { Vec3 o1 = GetTransform(xpos[k], ypos[k] + tief[k] * yd, zpos[k]); Vec3 o2 = GetTransform(xpos[4], ypos[4] + tief[4] * yd, zpos[4]); Vec3 r1 = GetTransform(xpos[pu], ypos[pu] + tief[pu] * yd, zpos[pu]); Vec3 r2 = GetTransform(xpos[4], ypos[4] + tief[4] * yd, zpos[4]); /* ox = xpos[k] - xpos[4]; oy = ypos[k] + tief[k] * yd - ypos[4] - tief[4] * yd; oz = zpos[k] - zpos[4]; rx = xpos[pu] - xpos[4]; ry = ypos[pu] + tief[pu] * yd - ypos[4] - tief[4] * yd; rz = zpos[pu] - zpos[4]; */ ox = o1.X - o2.X; oy = o1.Y - o2.Y; oz = o1.Z - o2.Z; rx = r1.X - r2.X; ry = r1.Y - r2.Y; rz = r1.Z - r2.Z; // Apply Transformation /* Vec3 ovec = GetTransform(ox, oy, oz); Vec3 rvec = GetTransform(rx, ry, rz); ox = ovec.X; oy = ovec.Y; oz = ovec.Z; rx = rvec.X; ry = rvec.Y; rz = rvec.Z; */ /* Dann wird das Kreuzprodukt gebildet, um einen Vergleichsvektor zu haben. */ xv = oy * rz - oz * ry; yv = oz * rx - ox * rz; zv = ox * ry - oy * rx; normals[k] = new Vec3(xv, yv, zv); /* Der Winkel ist nun das Skalarprodukt mit (0,-1,0)= Lichtstrahl */ /* mit Vergleichsvektor (Beide nachträglich normiert ) */ winkel = Math.Acos((yv) / (Math.Sqrt(xv * xv + yv * yv + zv * zv))); winkel = 1 - winkel; if (winkel < 0) winkel = 0; if (winkel > 1) winkel = 1; wert = (256 - (256 * winkel)); if (wert < 0) wert = 0; col[k] = 256 - wert; if (col[k] > 256 - 1) col[k] = 256 - 1; if (col[k] < 1) col[k] = 1; if (use4Points) { PixelInfo pInfo = null; if (borderPoints[k] == null) { pInfo = new PixelInfo(); borderPoints[k] = pInfo; } else { pInfo = borderPoints[k]; } pInfo.Coord.X = xpos[k]; pInfo.Coord.Y = ypos[k] + tief[k] * yd; pInfo.Coord.Z = zpos[k]; pInfo.Normal = normals[k]; pInfo.IsInside = !invers; if (pinfoSet != null) pInfo.AdditionalInfo = pinfoSet[k]; } else { PixelInfo pInfo = null; if (pData.Points[pixelX, pixelY] == null) { // TODO: Später Querschnitt aus allen Einzelwinkeln bestimmen pInfo = new PixelInfo(); pData.Points[pixelX, pixelY] = pInfo; pInfo.Coord.X = xpos[k]; pInfo.Coord.Y = ypos[k] + tief[k] * yd; pInfo.Coord.Z = zpos[k]; pInfo.IsInside = !invers; } else { pInfo = pData.Points[pixelX, pixelY]; pInfo.IsInside = !invers; } pInfo.Normal = normals[k]; if (k == 0 || k == 3) { // Debug only (um die reale Position zu ermitteln) if (pinfoSet != null) pInfo.AdditionalInfo = pinfoSet[k]; } // TODO: Auch die Normalen übertragen } } else { int indexX = 0, indexY = 0; if (pixelX >= 0 && pixelY >= 0) { switch (k) { case 0: indexX = pixelX + 1; indexY = pixelY; break; case 1: indexX = pixelX + 1; indexY = pixelY + 1; break; case 2: indexX = pixelX; indexY = pixelY + 1; break; case 3: indexX = pixelX; indexY = pixelY; break; } if (indexX < pData.Width && indexY < pData.Height) pData.Points[indexX, indexY] = null; } col[k] = 0; } } // Zusatzinformationen der anderen Pixel aufbauen if (use4Points) { int indexX = pixelX; int indexY = pixelY; int kNeigbour1 = 0; int kNeigbour2 = 0; for (k = 0; k < 4; k++) { switch (k) { case 0: indexX = pixelX + 1; indexY = pixelY + 1; kNeigbour1 = 1; kNeigbour2 = 2; break; case 1: indexX = pixelX; indexY = pixelY + 1; kNeigbour1 = 2; kNeigbour2 = 3; break; case 2: indexX = pixelX; indexY = pixelY; kNeigbour1 = 3; kNeigbour2 = 0; break; case 3: indexX = pixelX + 1; indexY = pixelY; kNeigbour1 = 0; kNeigbour2 = 1; break; } PixelInfo otherP1 = borderPoints[kNeigbour1]; PixelInfo otherP2 = borderPoints[kNeigbour2]; if (otherP1 == null) otherP1 = otherP2; if (otherP2 == null) otherP2 = otherP1; if (otherP1 != null) { PixelInfo pInfo = new PixelInfo(); pInfo.IsInside = !invers; pInfo.Coord.X = (otherP1.Coord.X + otherP2.Coord.X) / 2.0; pInfo.Coord.Y = (otherP1.Coord.Y + otherP2.Coord.Y) / 2.0; pInfo.Coord.Z = (otherP1.Coord.Z + otherP2.Coord.Z) / 2.0; pInfo.Normal.X = (otherP1.Normal.X + otherP2.Normal.X) / 2.0; pInfo.Normal.Y = (otherP1.Normal.Y + otherP2.Normal.Y) / 2.0; pInfo.Normal.Z = (otherP1.Normal.Z + otherP2.Normal.Z) / 2.0; if (otherP1.AdditionalInfo != null && otherP2.AdditionalInfo != null) { AdditionalPointInfo pinfo = new AdditionalPointInfo(); pinfo.blue = (otherP1.AdditionalInfo.blue + otherP2.AdditionalInfo.blue) / 2.0; pinfo.green = (otherP1.AdditionalInfo.green + otherP2.AdditionalInfo.green) / 2.0; pinfo.red = (otherP1.AdditionalInfo.red + otherP2.AdditionalInfo.red) / 2.0; pInfo.AdditionalInfo = pinfo; } if (indexX < pData.Width && indexY < pData.Height) { pData.Points[indexX, indexY] = pInfo; } } } } return ((int)col[0]); }
/// <summary> /// Im Gegensatz zu klasischen Funktion Winkel wird hier von vorn gerechnet, /// die isometrische Ansicht entfällt. /// </summary> /// <param name="zykl"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="zz"></param> /// <param name="xd"></param> /// <param name="yd"></param> /// <param name="zd"></param> /// <param name="zzd"></param> /// <param name="wix"></param> /// <param name="wiy"></param> /// <param name="wiz"></param> /// <param name="jx"></param> /// <param name="jy"></param> /// <param name="jz"></param> /// <param name="jzz"></param> /// <param name="formula"></param> /// <param name="use4Points">Hier wird unterschieden, ob nur dieser Punkt, oder auch seine Nachbarpixel /// betrachtet werden.</param> /// <returns></returns> public double FixPoint(long zykl, double x, double y, double z, double zz, double xd, double yd, double zd, double zzd, double wix, double wiy, double wiz, double jx, double jy, double jz, double jzz, int formula, bool invers, int pixelX, int pixelY, bool use4Points) { if (zd == 0) { Console.WriteLine("Error in WinkelPerspective: zd==0"); return 0; } double m = 0; double xv = 0, yv = 0, zv = 0, winkel = 0, yn = 0, diff = 0; double xn = 0, zn = 0, zzn = 0, xm = 0, ym = 0, zm = 0, zzm = 0; double ox = 0, oy = 0, oz = 0, rx = 0, ry = 0, rz = 0; double[] tief = new double[5]; double[] xpos = new double[5]; double[] ypos = new double[5]; // Die ungenaue Variante von tief[] double[] zpos = new double[5]; double startwert = 0; int k = 0; double wert = 0; int pu = 0; double distance = 0.09; double xDistance = distance * 6.0; double zDistance = distance * 6.0; // Eventuell während der Berechnung entstehende Zusatzinfos für alle 4 Punkte. AdditionalPointInfo[] pinfoSet = null; // Use combination of all computed AdditionalPointInfo for smoother colors. AdditionalPointInfo additionalPointInfoCombination = new AdditionalPointInfo(); additionalPointInfoCombination.blue = 0; additionalPointInfoCombination.red = 0; additionalPointInfoCombination.green = 0; if (mInternFormula != null && mInternFormula.additionalPointInfo != null) { pinfoSet = new AdditionalPointInfo[5]; } for (k = 4; k >= 0; k--) { switch (k) { case 2: /* oben */ xn = x; yn = y; zn = z - zDistance * zd; zzn = zz + zDistance * zzd; break; case 1: /* rechts */ xn = x + xDistance * xd; yn = y; zn = z; zzn = zz; break; case 0: /* unten */ xn = x; yn = y; zn = z + zDistance * zd; zzn = zz + zDistance * zzd; break; case 3: /* links */ xn = x - xDistance * xd; yn = y; zn = z; zzn = zz; break; case 4: /* mitte */ xn = x; yn = y; zn = z; zzn = zz; break; } xpos[k] = xn; ypos[k] = yn; zpos[k] = zn; if (Rechne(xn, yn, zn, zzn, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { for (m = 0; m >= -4.0; m -= 0.2) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (!(Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) break; } } else { for (m = 0; m <= 4.0; m += 0.2) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { m -= 0.2; break; } } } if ((m > -3.9) && (m < 3.9)) { startwert = m + 0.2; diff = 0.1; while (diff >= 0.00001) { m = startwert - diff; zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (0L == Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers)) startwert = m + diff; else startwert = m; diff /= 2.0; } tief[k] = m; } else { // Fast Kopie der obigen Formeln if (Rechne(xn, yn, zn, zzn, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { for (m = 0; m >= -8.0; m -= 0.02) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (!(Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) { if (!(Rechne(xm, ym + yd / 2.0, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0)) { break; } else { // break; // Staubzähler erhöhen } } } } else { for (m = 0; m <= 8.0; m += 0.02) { zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { if (Rechne(xm, ym + yd / 2.0, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers) > 0) { m -= 0.02; break; } else { // Staubzähler erhöhen //m -= 0.02; //break; } } } } if ((m > -7.9) && (m < 7.9)) { startwert = m + 0.02; diff = 0.01; while (diff >= 0.00001) { m = startwert - diff; zm = zn; xm = xn; ym = yn + m * yd; zzm = zzn; if (0L == Rechne(xm, ym, zm, zzm, zykl, wix, wiy, wiz, jx, jy, jz, jzz, formula, invers)) startwert = m + diff; else startwert = m; diff /= 2.0; } tief[k] = m; } else { tief[k] = 20; } // Ende: Fast Kopie der obigen Formeln } if (pinfoSet != null) { pinfoSet[k] = new AdditionalPointInfo(mInternFormula.additionalPointInfo); } } // Die Normalen der 4 Randpunkte Vec3[] normals = new Vec3[4]; for (k = 0; k < 4; k++) { pu = k + 1; if (k == 3) pu = 0; /* Die drei Punkte entsprechen tief[4] tief[k] und tief[pu] */ /* Zuerst wird tief abgezogen */ if ((tief[k] < 19) && (tief[pu] < 19) && tief[4] < 19) { Vec3 o1 = GetTransform(xpos[k], ypos[k] + tief[k] * yd, zpos[k]); Vec3 o2 = GetTransform(xpos[4], ypos[4] + tief[4] * yd, zpos[4]); Vec3 r1 = GetTransform(xpos[pu], ypos[pu] + tief[pu] * yd, zpos[pu]); Vec3 r2 = GetTransform(xpos[4], ypos[4] + tief[4] * yd, zpos[4]); /* ox = xpos[k] - xpos[4]; oy = ypos[k] + tief[k] * yd - ypos[4] - tief[4] * yd; oz = zpos[k] - zpos[4]; rx = xpos[pu] - xpos[4]; ry = ypos[pu] + tief[pu] * yd - ypos[4] - tief[4] * yd; rz = zpos[pu] - zpos[4]; */ ox = o1.X - o2.X; oy = o1.Y - o2.Y; oz = o1.Z - o2.Z; rx = r1.X - r2.X; ry = r1.Y - r2.Y; rz = r1.Z - r2.Z; /* ox = xpos[k] - xpos[4]; oy = ypos[k] + tief[k] * yd - ypos[4] - tief[4] * yd; oz = zpos[k] - zpos[4]; rx = xpos[pu] - xpos[4]; ry = ypos[pu] + tief[pu] * yd - ypos[4] - tief[4] * yd; rz = zpos[pu] - zpos[4]; */ // Apply Transformation /* Vec3 ovec = GetTransform(ox, oy, oz); Vec3 rvec = GetTransform(rx, ry, rz); ox = ovec.X; oy = ovec.Y; oz = ovec.Z; rx = rvec.X; ry = rvec.Y; rz = rvec.Z; */ /* Dann wird das Kreuzprodukt gebildet, um einen Vergleichsvektor zu haben. */ xv = oy * rz - oz * ry; yv = oz * rx - ox * rz; zv = ox * ry - oy * rx; normals[k] = new Vec3(xv, yv, zv); /* Der Winkel ist nun das Skalarprodukt mit (0,-1,0)= Lichtstrahl */ /* mit Vergleichsvektor (Beide nachträglich normiert ) */ winkel = Math.Acos((yv) / (Math.Sqrt(xv * xv + yv * yv + zv * zv))); winkel = 1 - winkel; if (winkel < 0) winkel = 0; if (winkel > 1) winkel = 1; wert = (256 - (256 * winkel)); if (wert < 0) wert = 0; col[k] = 256 - wert; if (col[k] > 256 - 1) col[k] = 256 - 1; if (col[k] < 1) col[k] = 1; // Pixelposition im ausgegebenen Bild int indexX = 0, indexY = 0; if (use4Points) { switch (k) { case 0: indexX = pixelX + 1; indexY = pixelY; break; case 1: indexX = pixelX + 1; indexY = pixelY + 1; break; case 2: indexX = pixelX; indexY = pixelY + 1; break; case 3: indexX = pixelX; indexY = pixelY; break; } if (k == 3) { if (indexX < pData.Width && indexY < pData.Height) { if (pData.Points[indexX, indexY] == null) { PixelInfo pInfo = new PixelInfo(); pInfo.Coord.X = xpos[k]; pInfo.Coord.Y = ypos[k] + tief[k] * yd; pInfo.Coord.Z = zpos[k]; pInfo.Normal = normals[k]; pData.Points[indexX, indexY] = pInfo; if (pinfoSet != null) pInfo.AdditionalInfo = pinfoSet[k]; } } } } else { PixelInfo pInfo = null; if (pData.Points[pixelX, pixelY] == null) { // TODO: Später Querschnitt aus allen Einzelwinkeln bestimmen pInfo = new PixelInfo(); pData.Points[pixelX, pixelY] = pInfo; pInfo.Coord.X = xpos[k]; pInfo.Coord.Y = ypos[k] + tief[k] * yd; pInfo.Coord.Z = zpos[k]; } else { pInfo = pData.Points[pixelX, pixelY]; } pInfo.Normal = normals[k]; if (pinfoSet != null) pInfo.AdditionalInfo = pinfoSet[k]; // TODO: Auch die Normalen übertragen } } else { int indexX = 0, indexY = 0; if (pixelX >= 0 && pixelY >= 0) { switch (k) { case 0: indexX = pixelX + 1; indexY = pixelY; break; case 1: indexX = pixelX + 1; indexY = pixelY + 1; break; case 2: indexX = pixelX; indexY = pixelY + 1; break; case 3: indexX = pixelX; indexY = pixelY; break; } if (indexX < pData.Width && indexY < pData.Height) pData.Points[indexX, indexY] = null; } col[k] = 0; } } /* // Oberflächenkrümmung bestimmen double derivation = 0; // Zentrum der 4 Randpunkte mit dem Mittelpunkt vergleichen. double ycenter = 0; if (tief[4] < 19) { int pointsCount = 0; double ymax = double.MinValue; double ymin = double.MaxValue; double currentY = 0; for (k = 0; k < 4; k++) { if (tief[k] < 19) { currentY = ypos[k] + tief[k] * yd; ycenter += currentY; if (currentY > ymax) ymax = currentY; if (currentY < ymin) ymin = currentY; pointsCount++; } } if (pointsCount > 0) ycenter = ycenter / ((double)pointsCount); double maxdiff = Math.Max((yd + xd + zd) / 2.0, ymax - ymin); // derivation soll eigentlich die lokale Erhöhung anzeigen, // wird aber zur Zeit nicht mehr in PictureArt verwendet derivation = 2.0 * (ypos[4] - ycenter) / (maxdiff); // Dasselbe über die Normalen: double winkel1 = 0; double winkel2 = 0; if (normals[0] != null && normals[2] != null) winkel1 = Math.Acos((normals[0].X * normals[2].X + normals[0].Y * normals[2].Y + normals[0].Z * normals[2].Z) / (Math.Sqrt(normals[0].X * normals[0].X + normals[0].Y * normals[0].Y + normals[0].Z * normals[0].Z) * Math.Sqrt(normals[2].X * normals[2].X + normals[2].Y * normals[2].Y + normals[2].Z * normals[2].Z))); if (normals[1] != null && normals[3] != null) winkel2 = Math.Acos((normals[1].X * normals[3].X + normals[1].Y * normals[3].Y + normals[1].Z * normals[3].Z) / (Math.Sqrt(normals[1].X * normals[1].X + normals[1].Y * normals[1].Y + normals[1].Z * normals[1].Z) * Math.Sqrt(normals[3].X * normals[3].X + normals[3].Y * normals[3].Y + normals[3].Z * normals[3].Z))); if (derivation < 0) derivation = -Math.Max(winkel, winkel2); else derivation = Math.Max(winkel, winkel2); if (pixelX >= 0 && pixelY >= 0) { if (pixelX < pData.Width && pixelY < pData.Height) if (pData.Points[pixelX, pixelY] != null) pData.Points[pixelX, pixelY].derivation = derivation; if (pixelX + 1 < pData.Width && pixelY < pData.Height) if (pData.Points[pixelX + 1, pixelY] != null) pData.Points[pixelX + 1, pixelY].derivation = derivation; if (pixelX < pData.Width && pixelY + 1 < pData.Height) if (pData.Points[pixelX, pixelY + 1] != null) pData.Points[pixelX, pixelY + 1].derivation = derivation; if (pixelX + 1 < pData.Width && pixelY + 1 < pData.Height) if (pData.Points[pixelX + 1, pixelY + 1] != null) pData.Points[pixelX + 1, pixelY + 1].derivation = derivation; } } */ // Farben feiner machen: if (pinfoSet != null) { PixelInfo pInfo = pData.Points[pixelX, pixelY]; if (pInfo != null) { pInfo.AdditionalInfo = pinfoSet[0]; for (int i = 1; i <= 4; i++) { if (pInfo.AdditionalInfo != null && pinfoSet[i] != null) { pInfo.AdditionalInfo.red += pinfoSet[i].red; pInfo.AdditionalInfo.green += pinfoSet[i].green; pInfo.AdditionalInfo.blue += pinfoSet[i].blue; } } pInfo.IsInside = !invers; } } return ((int)col[0]); }
/// <summary> /// Transformiert den angegebenen Punkt. /// Die Rotationen um (0,0,0) werden dabei nicht beruecksichtigt (outdated). /// </summary> /// <param name="pos"></param> /// <returns></returns> protected Vec3 Transform(double x, double y, double z) { if (mProjection != null) { Vec3 projPoint = mProjection.Transform(new Vec3(x, y, z)); x = projPoint.X; y = projPoint.Y; z = projPoint.Z; } if (mTransforms.Count > 0) { Vec3 vec = new Vec3(x, y, z); foreach (Transform3D trans in mTransforms) { vec = trans.Transform(vec); } x = vec.X; y = vec.Y; z = vec.Z; } return new Vec3(x, y, z); }
/// <summary> /// Compute surface data. /// </summary> protected void Generate(FracValues act_val, int zyklen, double screensize, int formula, bool perspective) { Random rand = new Random(); _maxUpdateSteps = ParameterDict.Current.GetInt("View.UpdateSteps"); double[] col = null; double xd, yd, zd; double x, y, z; double dephAdd = ParameterDict.Current.GetInt("View.DephAdd") * screensize; act_val = act_val.Clone(); Formulas formulas = new Formulas(_pData); _lastUsedFormulas = formulas; if (ParameterDict.Current["Intern.Formula.Source"].Trim() == "") { formulas.InternFormula = new Fractrace.TomoGeometry.VecRotMandel2d(); } else { Fractrace.TomoGeometry.TomoFormulaFactory fac = new Fractrace.TomoGeometry.TomoFormulaFactory(); formulas.InternFormula = fac.CreateFromString(ParameterDict.Current["Intern.Formula.Source"]); } if (formulas.InternFormula == null) return; formulas.InternFormula.Init(); double centerX = ParameterDict.Current.GetDouble("Scene.CenterX"); double centerY = ParameterDict.Current.GetDouble("Scene.CenterY"); double centerZ = ParameterDict.Current.GetDouble("Scene.CenterZ"); Rotation rotView = new Rotation(); rotView.Init(centerX, centerY, centerZ, ParameterDict.Current.GetDouble("Transformation.Camera.AngleX"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleY"), ParameterDict.Current.GetDouble("Transformation.Camera.AngleZ")); formulas.Transforms.Add(rotView); // TODO: only use in compatibility mode. Rotation rot = new Rotation(); rot.Init(); formulas.Transforms.Add(rot); if (_isRightView) { RightEyeView stereoTransform = new RightEyeView(); stereoTransform.Init(); formulas.Transforms.Add(stereoTransform); } col = formulas.col; _maxxIter = _width; _maxyIter = (int)(ParameterDict.Current.GetDouble("View.Deph") * screensize); if(IsSmallPreview()) _maxyIter = _maxxIter; _maxzIter = _height; int MINX_ITER = 0; int MINY_ITER = 0; int MINZ_ITER = 0; double fa1; int xschl = 0, yschl = 0, zschl = 0, xx = 0, yy = 0; double wix = 0, wiy = 0, wiz = 0; double jx = 0, jy = 0, jz = 0, jzz = 0; jx = ParameterDict.Current.GetDouble("Formula.Static.jx"); jy = ParameterDict.Current.GetDouble("Formula.Static.jy"); jz = ParameterDict.Current.GetDouble("Formula.Static.jz"); jzz = ParameterDict.Current.GetDouble("Formula.Static.jzz"); // Innenbereich int minCycle = (int)ParameterDict.Current.GetDouble("Formula.Static.MinCycle"); if (minCycle == 0) minCycle = zyklen; // Offset für den Maximalzyklus für die klassische 2D-Darstellung int cycleAdd = 128; wix = act_val.arc.x; wiy = act_val.arc.y; wiz = act_val.arc.z; xd = (act_val.end_tupel.x - act_val.start_tupel.x) / (_maxxIter - MINX_ITER); yd = (act_val.end_tupel.y - act_val.start_tupel.y) / (_maxyIter - MINY_ITER); zd = (act_val.end_tupel.z - act_val.start_tupel.z) / (_maxzIter - MINZ_ITER); if (_oldData != null) { yd = yd / (_updateCount); if (_updateCount < 5) { _maxyIter *= _updateCount; } } if (_transformUpdate) { yd *= 3.0; } double xcenter = (act_val.start_tupel.x + act_val.end_tupel.x) / 2.0; double ycenter = (act_val.start_tupel.y + act_val.end_tupel.y) / 2.0; double zcenter = (act_val.start_tupel.z + act_val.end_tupel.z) / 2.0; bool isYborder = true; // Projektion initialisieren und der Berechnung zuordnen: // TODO: Projektion über Einstellungen abwählbar machen double cameraDeph = act_val.end_tupel.y - act_val.start_tupel.y; cameraDeph *= ParameterDict.Current.GetDouble("Transformation.Perspective.Cameraposition"); Vec3 camera = new Vec3(xcenter, act_val.end_tupel.y + cameraDeph, zcenter); Vec3 viewPoint = new Vec3(xcenter, act_val.end_tupel.y, zcenter); Projection proj = new Projection(camera, viewPoint); if (ParameterDict.Current.GetBool("View.Perspective")) formulas.Projection = proj; // Bei der Postererstellung werden die Parameter der räumlichen Projektion auf das mittlere Bild // ausgerichtet und anschließend die Grenzen verschoben double xPoster = ParameterDict.Current.GetInt("View.PosterX"); double zPoster = ParameterDict.Current.GetInt("View.PosterZ"); double xDiff = act_val.end_tupel.x - act_val.start_tupel.x; double zDiff = act_val.end_tupel.z - act_val.start_tupel.z; act_val.end_tupel.x += xDiff * xPoster; act_val.start_tupel.x += xDiff * xPoster; act_val.end_tupel.z += zDiff * zPoster; act_val.start_tupel.z += zDiff * zPoster; // Start der Iteration in der Reihenfolge: z,x,y (y entspricht der Tiefe) z = act_val.end_tupel.z + zd; for (zschl = (int)(_maxzIter); zschl >= (MINZ_ITER); zschl -= 1) { // Nur wenn der Scheduler die Erlaubnis gibt, zschl zu benutzen, // die Berechnung ausführen (sonst nächste Iteration) if (IsAvailable(_maxzIter - zschl)) { System.Windows.Forms.Application.DoEvents(); z = act_val.end_tupel.z - (double)zd * (_maxzIter - zschl); bool minYDetected = false; for (xschl = (int)(MINX_ITER); xschl <= _maxxIter; xschl += 1) { if (_abort) { return; } x = act_val.start_tupel.x + (double)xd * xschl; double miny = 0; isYborder = true; xx = xschl; yy = _maxzIter - zschl; if (double.IsNaN(x) ) return ; // Used for better start values in update iteration double yAdd = rand.NextDouble() * yd; // In last computation a voxel ist found at (xx,zz) bool centerIsSet = false; // In last computation at least on voxel ist found near (xx,zz) bool areaIsSet = false; double yAddCenter = 0; bool needComputing = true; if (_oldPictureData != null) { needComputing = false; PixelInfo pxInfoTest = _oldPictureData.Points[xx, yy]; if (pxInfoTest != null && pxInfoTest.Coord != null) { yAddCenter = pxInfoTest.Coord.Y; yAdd = yAddCenter; centerIsSet = true; } for (int xxi = -1; xxi <= 1; xxi++) { for (int yyi = -1; yyi <= 1; yyi++) { int xxposi = xx + xxi; int yyposi = yy + yyi; if (xxposi >= 0 && xxposi <= _maxxIter && yyposi >= 0 && yyposi <= _maxzIter) { PixelInfo pxInfo = _oldPictureData.Points[xxposi, yyposi]; if (pxInfo != null && pxInfo.Coord != null) { areaIsSet = true; double yAddTemp = pxInfo.Coord.Y; if (yAdd < yAddTemp || !centerIsSet) yAdd = yAddTemp; } } } } } if (yAdd + yd < act_val.end_tupel.y) { if (centerIsSet) { if (yAddCenter + 4.0 * yd < yAdd) { needComputing = true; yAdd = yAdd - act_val.end_tupel.y + 2.0 * ((double)_updateCount) * yd + rand.NextDouble() * yd; _gData.Picture[xx, yy] = _oldData.Picture[xx, yy]; } } else { if (areaIsSet) { needComputing = true; yAdd = rand.NextDouble() * yd; } } } if (needComputing) { // yadd cannot be easy handled (because of inside rendering). for (yschl = (int)(_maxyIter); yschl >= MINY_ITER - dephAdd; yschl -= 1) { if (_abort) return; if (xx >= 0 && xx < _width && yy >= 0 && yy < _height) { if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { // aha, noch zeichnen // Test, ob Schnitt mit Begrenzung vorliegt y = act_val.end_tupel.y - (double)yd * (_maxyIter - yschl); y += yAdd; if (double.IsNaN(x) || double.IsNaN(y) || double.IsNaN(z)) return; fa1 = 0; int usedCycles = 0; bool inverse = false; if (_gData == null) { System.Diagnostics.Debug.WriteLine("Error: GData == null"); return; } if ((_gData.Picture)[xx, yy] == 0) usedCycles = formulas.Rechne(x, y, z, 0, zyklen, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); if ((_gData.Picture)[xx, yy] == 2) {// Inverse computing inverse = true; usedCycles = formulas.Rechne(x, y, z, 0, minCycle, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse); } if (usedCycles == 0) { if (!minYDetected) miny = yschl; minYDetected = true; // Iteration ist nicht abgebrochen, also weiterrechnen: int oldPictureInfo = (_gData.Picture)[xx, yy]; // pictureInfo wird eventuell zurückgesetzt, wenn // die Farbberechnung wiederholt wird. _gData.Picture[xx, yy] = 1; // Punkt als gesetzt markieren VoxelInfo vInfo = new VoxelInfo(); _gData.PointInfo[xx, yy] = vInfo; vInfo.i = x; vInfo.j = y; vInfo.k = z; cycleAdd = 1024; if (minCycle >= 0) { cycleAdd = minCycle - zyklen; } if (isYborder) { // es liegt Schnitt mit Begrenzung vor fa1 = formulas.Rechne(x, y, z, 0, zyklen + cycleAdd, wix, wiy, wiz, jx, jy, jz, jzz, formula, false); if (fa1 == 0) { fa1 = -1; (_gData.Picture)[xx, yy] = 2; // Punkt nicht als gesetzt markieren } else fa1 = 255 * fa1 / (zyklen + cycleAdd); // debug only: alle Farbwerte auf 1 setzen col[0] = col[1] = col[2] = col[3] = 255; } else {// innerer Punkt if (inverse) { if (IsSmallPreview()) { fa1 = formulas.RayCastAt(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { fa1 = formulas.FixPoint(minCycle, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } } else { if (IsSmallPreview()) { fa1 = formulas.RayCastAt(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); } else { fa1 = formulas.FixPoint(zyklen, x, y, z, 0, xd, yd, zd, 0, wix, wiy, wiz, jx, jy, jz, jzz, formula, inverse, xx, yy, true); fa1 = (col[0] + col[1] + col[2] + col[3]) / 4.0; } } } } } } isYborder = false; } if ((_gData.Picture)[xx, yy] == 0 || (_gData.Picture)[xx, yy] == 2) { if (_oldPictureData != null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } if (_oldData != null && _updateCount > 2) { if (_oldPictureData.Points[xx, yy] != null) { if (_pData.Points[xx, yy] == null) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } else { if (_pData.Points[xx, yy].Coord.Y < _oldPictureData.Points[xx, yy].Coord.Y) { _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } } else { // Get the old values: _pData.Points[xx, yy] = _oldPictureData.Points[xx, yy]; } } } } }
/// <summary> /// Benutzung der Vektorrotation. /// </summary> /// <param name="ar"></param> /// <param name="ai"></param> /// <param name="aj"></param> /// <param name="ak"></param> /// <param name="br"></param> /// <param name="bi"></param> /// <param name="bj"></param> /// <param name="bk"></param> /// <param name="zkl"></param> /// <param name="invers"></param> /// <returns></returns> long H7(double ar, double ai, double aj, double ak, double br, double bi, double bj, double bk, long zkl, bool invers) { double xx, yy, zz; long tw; int n; ai = 0; aj = 0; ak = 0; double x = 1, y = 0, z = 0; xx = x * x; yy = y * y; zz = z * z; tw = 0; double r = Math.Sqrt(xx + yy + zz); VecRotation vecRot = new VecRotation(); x = 1; // Um den Startwinkel eindeutig zu definieren. for (n = 1; n < zkl; n++) { double theta = Math.Atan2(Math.Sqrt(xx + yy), z); double phi = Math.Atan2(y, x); vecRot.X = y; vecRot.Y = x; vecRot.Z = z; vecRot.Angle = theta; // vecRot.angle = 0.03; vecRot.X = x; vecRot.Y = z; vecRot.Z = y; vecRot.Angle = phi; /* vecRot.x = 0.4; vecRot.y = 0.2; vecRot.z = 0.8; vecRot.angle = phi; */ y += bj; x += bi; z += br; Vec3 pos = new Vec3(x, y, z); Vec3 newPos = vecRot.getTransform(pos); x = newPos.X; y = newPos.Y; z = newPos.Z; xx = x * x; yy = y * y; zz = z * z;// aak = ak * ak; r = Math.Sqrt(xx + yy + zz); x *= r; y *= r; z *= r; if (r > gr) { tw = n; break; } } if (invers) { if (tw == 0) tw = 1; else tw = 0; } return (tw); }
/// <summary> /// Liefert die Farbe der Oberfläche entsprechend der Normalen. /// </summary> /// <param name="normal"></param> /// <returns></returns> protected virtual Vec3 GetLight(Vec3 normal) { Vec3 retVal = new Vec3(backColorRed, backColorGreen, backColorBlue); if (!useLight) { return new Vec3(0.5, 0.5, 0.5); } if (normal == null) return retVal; double weight_shini = shininessFactor; double weight_diffuse = 1 - weight_shini; double norm = Math.Sqrt(normal.X * normal.X + normal.Y * normal.Y + normal.Z * normal.Z); // Der Winkel ist nun das Skalarprodukt mit (0,-1,0)= Lichtstrahl // mit Vergleichsvektor (Beide nachträglich normiert ) double angle = 0; if (norm == 0) return retVal; Vec3 lightVec = new Vec3(lightRay.X, lightRay.Y, lightRay.Z); lightVec.Normalize(); double norm2 = lightVec.Norm; angle = Math.Acos((normal.X * lightVec.X + normal.Y * lightVec.Y + normal.Z * lightVec.Z) / (norm * norm2)) / (Math.PI / 2.0); angle = 1 - angle; if (angle < 0) angle = 0; if (angle > 1) angle = 1; double light = weight_diffuse * angle + weight_shini * Math.Pow(angle, shininess); // double light =(Math.Pow(angle, 128)); // double light = angle; if (light < 0) light = 0; if (light > 1) light = 1; retVal.X = light; retVal.Y = light; retVal.Z = light; return retVal; }
/// <summary> /// Transform the point (x,y,z) corresponding the defined rotations. /// </summary> /// <param name="x">The x.</param> /// <param name="y">The y.</param> /// <param name="z">The z.</param> /// <returns></returns> public Vec3 GetTransformWithoutProjection(double x, double y, double z) { Vec3 retVal = new Vec3(); double a, f, re, im, xmi, ymi, zmi; try { if (mProjection != null) { Vec3 projPoint = mProjection.ReverseTransform(new Vec3(x, y, z)); x = projPoint.X; y = projPoint.Y; z = projPoint.Z; } if (mTransforms.Count > 0) { Vec3 vec = new Vec3(x, y, z); foreach (Transform3D trans in mTransforms) { vec = trans.Transform(vec); } x = vec.X; y = vec.Y; z = vec.Z; } /* Einbeziehung des Winkels */ f = Math.PI / 180.0; /*xmi=(x1-x2)/2;ymi=(y1+y2)/2;zmi=(z1+z2)/2;*/ // Drehung xmi = 0; ymi = 0; zmi = 0; x -= xmi; y -= ymi; z -= zmi; re = Math.Cos(mGlobalAngleZ * f); im = Math.Sin(mGlobalAngleZ * f); a = re * x - im * y; y = re * y + im * x; x = a; // Neigung re = Math.Cos(mGlobalAngleY * f); im = Math.Sin(mGlobalAngleY * f); a = re * z - im * x; x = re * x + im * z; z = a; // Kippen re = Math.Cos(mGlobalAngleX * f); im = Math.Sin(mGlobalAngleX * f); a = re * y - im * z; z = re * z + im * y; y = a; x += xmi; y += ymi; z += zmi; retVal.X = x; retVal.Y = y; retVal.Z = z; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); retVal.X = x; retVal.Y = y; retVal.Z = z; } return retVal; }
/// <summary> /// Test, if the given point is inside the sharp shadow. /// Returns the number of intersection with the ray and the fractal, but not more than maxIntersections. /// /// </summary> /// <param name="point"></param> /// <param name="ray"></param> /// <param name="rayLenght"></param> /// <returns></returns> protected int IsInSharpShadow(Vec3 point, Vec3 ray, double rayLenght, bool inverse, int maxIntersections, int steps) { //int steps = 100; inverse = false; double dSteps = steps; double dist = 0; int shadowCount = 0; for (int gSteps = 0; gSteps < 6; gSteps++) { dist = rayLenght / dSteps; Vec3 currentPoint = new Vec3(point); currentPoint.Add(ray.Mult(dist)); for (int i = 0; i < steps; i++) { currentPoint.Add(ray.Mult(dist)); if (formula.TestPoint(currentPoint.X, currentPoint.Y, currentPoint.Z, inverse)) { shadowCount++; if (shadowCount >= maxIntersections) return maxIntersections; } else { // return false; } } rayLenght /= 1.4; } return shadowCount; }
/// <summary> /// Die Berechnung wird gestartet. /// </summary> /// <param name="x">x-Position in Ansichtskoordinaten</param> /// <param name="y">y-Position in Ansichtskoordinaten</param> /// <param name="z">z-Position in Ansichtskoordinaten</param> /// <param name="zz">zz-Position in Ansichtskoordinaten (alt)</param> /// <param name="zykl">Benutzte Zyklen</param> /// <param name="wix">Globaler Winkel X</param> /// <param name="wiy">Globaler Winkel Y</param> /// <param name="wiz">Globaler Winkel Z</param> /// <param name="jx">Julia Parameter x</param> /// <param name="jy">Julia Parameter y</param> /// <param name="jz">Julia Parameter z</param> /// <param name="jzz">Julia Parameter zz</param> /// <param name="formula">Formel-ID</param> /// <param name="invers">Gibt an, ob von innen gerechnet wird.</param> /// <returns></returns> public int Rechne(double x, double y, double z, double zz, long zykl, double wix, double wiy, double wiz, double jx, double jy, double jz, double jzz, int formula, bool invers) { if (double.IsNaN(x) || double.IsNaN(y) || double.IsNaN(z)) return -1; old_jx = jx; old_jy = jy; old_jz = jz; old_jzz = jzz; old_formula = formula; long we = 0; double a, f, re, im, xmi, ymi, zmi; mGlobalAngleX = wix; mGlobalAngleY = wiy; mGlobalAngleZ = wiz; try { if (mProjection != null) { Vec3 projPoint = mProjection.Transform(new Vec3(x, y, z)); x = projPoint.X; y = projPoint.Y; z = projPoint.Z; } if (mTransforms.Count > 0) { Vec3 vec = new Vec3(x, y, z); foreach (Transform3D trans in mTransforms) { vec = trans.Transform(vec); } x = vec.X; y = vec.Y; z = vec.Z; } /* Einbeziehung des Winkels */ // Backward compatibility to old formulas with rotation with center=(0,0,0) if (wiz != 0 || wiy != 0.0 || wiz != 0) { f = Math.PI / 180.0; // Drehung xmi = 0; ymi = 0; zmi = 0; x -= xmi; y -= ymi; z -= zmi; re = Math.Cos(wiz * f); im = Math.Sin(wiz * f); a = re * x - im * y; y = re * y + im * x; x = a; // Neigung re = Math.Cos(wiy * f); im = Math.Sin(wiy * f); a = re * z - im * x; x = re * x + im * z; z = a; // Kippen re = Math.Cos(wix * f); im = Math.Sin(wix * f); a = re * y - im * z; z = re * z + im * y; y = a; x += xmi; y += ymi; z += zmi; } // Weitere Transformationen: switch (formula) { case -2: /* Interne Formel verwenden: als Jula-Menge */ we = 1; if (mInternFormula != null) { if (mInternFormula is GestaltFormula) { if (mInternFormula.additionalPointInfo != null) mInternFormula.additionalPointInfo.Clear(); GestaltFormula gestaltFormula = (GestaltFormula)mInternFormula; bool inset = gestaltFormula.GetBool(x, y, z); if (inset) we = 0; if (invers) { if (we == 0) we = 1; else we = 0; } } else we = mInternFormula.InSet(x, y, z, jx, jy, jz, jzz, zykl, invers); } break; case -1: /* Interne Formel verwenden: als Mandelbrotmenge */ we = 1; if (mInternFormula != null) { if (mInternFormula is GestaltFormula) { if (mInternFormula.additionalPointInfo != null) mInternFormula.additionalPointInfo.Clear(); GestaltFormula gestaltFormula = (GestaltFormula)mInternFormula; bool inset = gestaltFormula.GetBool(x, y, z); if (inset) we = 0; if (invers) { if (we == 0) we = 1; else we = 0; } } else we = mInternFormula.InSet(jx, jy, jz, x, y, z, zz, zykl, invers); } break; case 0: /* Apfel k */ //we= Komp(z,zz,x,y,zykl); we = 1; if ((x * x + y * y + z * z) < zykl / 100.0) we = 0L; break; case 1: /* Julia k */ we = Komp(x, y, z, zz, zykl); break; case 2: /* Misch_a k */ we = Komp(x, z, y, zz, zykl); break; case 3: /* Misch_b k */ we = Komp(zz, y, z, x, zykl); break; case 4: /* Drachen_a */ we = Dra(z, zz, x, y, zykl); break; case 5: /* Drachen_b */ we = Dra(x, y, z, zz, zykl); break; case 6: /* Drachen_c */ we = Dra(x, z, y, zz, zykl); break; case 7: /* Drachen_d */ we = Dra(zz, y, z, x, zykl); break; case 8: /* Julia Qu */ we = Qu(x, y, z, zz, jx, jy, jz, jzz, zykl); break; case 9: /* Misch_a Qu */ we = Qu(x, y, z, zz, y, z, zz, x, zykl); break; case 10: /* Misch_b Qu */ we = Qu(y, zz, z, x, x, y, z, zz, zykl); break; case 11: /* Misch_c Qu */ we = Qu(x, y, z, zz, y, x, z, zz, zykl); break; case 12: /* Apfel_a H1 */ we = H1(jx, jy, jz, jzz, x, y, z, zz, zykl); break; case 13: /* Apfel_b H1 */ we = H1(zz, x, y, z, jzz, jx, jy, jz, zykl); break; case 14: /* Julia_a H1 */ we = H1(x, y, z, zz, jx, jy, jz, jzz, zykl); break; case 15: /* Julia_b H1 */ we = H1(zz, x, y, z, jzz, jx, jy, jz, zykl); break; case 16: /* Apfel_a H2 */ we = H2(jx, jy, jz, jzz, x, y, z, zz, zykl); break; case 17: /* Apfel_b H2 */ we = H2(jzz, jx, jy, jz, zz, x, y, z, zykl); break; case 18: /* Julia_a H2 */ we = H2(x, y, z, zz, jx, jy, jz, jzz, zykl); break; case 19: /* Julia_b H2 */ we = H2(zz, x, y, z, jzz, jx, jy, jz, zykl); break; case 20: /* Apfel H3 */ we = H3(jx, jy, jz, jzz, x, y, z, zz, zykl); break; case 21: /* Julia H3 (Ides Fraktal) */ we = H3(x, y, z, zz, jx, jy, jz, jzz, zykl); break; case 22: /* Misch_a H3 */ we = H3(x, y, z, zz, y, z, zz, x, zykl); break; case 23: /* Misch_b H3 */ we = H3(y, zz, z, x, x, y, z, zz, zykl); break; case 24: /* Mandelbulb3D */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Mandelbulb3D(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 25: /* Würfel */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Wuerfel(jx, jy, jz, jzz, x, y, z, zz, zykl); break; case 26: /* Julia H3 (Ides Fraktal) */ we = H3(x, y, zz, z, jx, jy, jz, jzz, zykl); break; case 27: /* Julia H4 (Ides Fraktal, verändert) */ we = H4(x, y, z, zz, jx, jy, jz, jzz, zykl); break; case 28: /* Mandelbulb 3D Julia */ we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl, invers); break; case 29: /* Abgeändertes Mandelbulb 3D */ we = H6(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 30: /* Mandelbulb3D */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Mandelbulb3D(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 31: /* Mandelbulb3D */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl, invers); break; case 32: /* Mandelbulb3D pow2 */ we = Mandelbulb3DPow2(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 33: /* Mandelbulb3D pow 2*/ we = Mandelbulb3DPow2(x, y, z, zz, jx, jy, jz, jzz, zykl, invers); break; case 34: /* Mandelbulb3D */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Mandelbulb3DPow8(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 35: /* Mandelbulb3D */ // we = Mandelbulb3D(x, y, z, zz, jx, jy, jz, jzz, zykl); we = Mandelbulb3DPow8(x, y, z, zz, jx, jy, jz, jzz, zykl, invers); break; case 36: // Mandel mit Vektorrotation we = H7(jx, jy, jz, jzz, x, y, z, zz, zykl, invers); break; case 37: // Julia mit Vektorrotation we = H7(x, y, z, zz, jx, jy, jz, jzz, zykl, invers); break; } return ((int)we); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); return 0; } }
/// <summary> /// Die Oberflächennormalen werden abgerundet. /// </summary> protected void CreateSmoothNormales() { normalesSmooth1 = new Vec3[pData.Width, pData.Height]; normalesSmooth2 = new Vec3[pData.Width, pData.Height]; // Normieren for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { PixelInfo pInfo = pData.Points[i, j]; if (pInfo != null) { // pInfo.Normal.Normalize(); normalesSmooth1[i, j] = pInfo.Normal; normalesSmooth1[i, j].Normalize(); } } } Vec3[,] currentSmooth = normalesSmooth1; Vec3[,] nextSmooth = normalesSmooth2; Vec3[,] tempSmooth; int smoothLevel = (int)ParameterDict.Current.GetDouble("Renderer.SmoothNormalLevel"); for (int currentSmoothLevel = 0; currentSmoothLevel < smoothLevel; currentSmoothLevel++) { // create nextSmooth for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { Vec3 center = null; center = currentSmooth[i, j]; PixelInfo pInfo = pData.Points[i, j]; // Test ohne smooth-Factor // Nachbarelemente zusammenrechnen Vec3 neighbors = new Vec3(); int neighborFound = 0; for (int k = -1; k <= 1; k++) { for (int l = -1; l <= 1; l++) { int posX = i + k; int posY = j + l; if (posX >= 0 && posX < pData.Width && posY >= 0 && posY < pData.Height) { Vec3 currentNormal = null; currentNormal = currentSmooth[i + k, j + l]; PixelInfo pInfo2 = pData.Points[i + k, j + l]; if (currentNormal != null) { double amount = 1; if (pInfo != null && pInfo2 != null) { double dist = pInfo.Coord.Dist(pInfo2.Coord); double dGlobal = maxPoint.Dist(minPoint); dGlobal /= 1500; if (dist < dGlobal) amount = 1.0; else if (dist > dGlobal && dist < 5.0 * dGlobal) amount = 1.0 - (dGlobal / dist / 5.0); else amount = 0; } neighbors.Add(currentNormal.Mult(amount)); neighborFound++; } } } } neighbors.Normalize(); if (center != null) { nextSmooth[i, j] = center; if (center != null || neighborFound > 1) { Vec3 center2 = center; center2.Mult(200); neighbors.Add(center2.Mult(4)); neighbors.Normalize(); nextSmooth[i, j] = neighbors; } } else { if (neighborFound > 4) { nextSmooth[i, j] = neighbors; } } } } tempSmooth = currentSmooth; currentSmooth = nextSmooth; nextSmooth = tempSmooth; } }
/// <summary> /// Initialisation with formula is needed for computing original coordinates. /// </summary> public override void Init(Formulas formula) { base.Init(formula); // Original data has to scale such that values fits into float range. Vec3 minPoint = new Vec3(0, 0, 0); Vec3 maxPoint = new Vec3(0, 0, 0); minPoint.X = Double.MaxValue; minPoint.Y = Double.MaxValue; minPoint.Z = Double.MaxValue; maxPoint.X = Double.MinValue; maxPoint.Y = Double.MinValue; maxPoint.Z = Double.MinValue; for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { PixelInfo pInfo = pData.Points[i, j]; if (pInfo != null) { Vec3 coord = formula.GetTransform(pInfo.Coord.X, pInfo.Coord.Y, pInfo.Coord.Z); if (coord.X < minPoint.X) minPoint.X = coord.X; if (coord.Y < minPoint.Y) minPoint.Y = coord.Y; if (coord.Z < minPoint.Z) minPoint.Z = coord.Z; if (coord.X > maxPoint.X) maxPoint.X = coord.X; if (coord.Y > maxPoint.Y) maxPoint.Y = coord.Y; if (coord.Z > maxPoint.Z) maxPoint.Z = coord.Z; } } } Vec3 center = new Vec3(0, 0, 0); center.X = (maxPoint.X + minPoint.X) / 2.0; center.Y = (maxPoint.Y + minPoint.Y) / 2.0; center.Z = (maxPoint.Z + minPoint.Z) / 2.0; double radius = maxPoint.X - minPoint.X + maxPoint.Y - minPoint.Y + maxPoint.Z - minPoint.Z; for (int i = 0; i < pData.Width; i++) { for (int j = 0; j < pData.Height; j++) { PixelInfo pInfo = pData.Points[i, j]; if (pInfo != null) { FloatPixelInfo floatPixelInfo = new FloatPixelInfo(); floatPixelInfo.Coord.X = (float)((pInfo.Coord.X - center.X) / radius); floatPixelInfo.Coord.Y = (float)((pInfo.Coord.Y - center.Y) / radius); floatPixelInfo.Coord.Z = (float)((pInfo.Coord.Z - center.Z) / radius); floatPixelInfo.AdditionalInfo = pInfo.AdditionalInfo; floatPixelInfo.IsInside = pInfo.IsInside; pInfo.Normal.Normalize(); floatPixelInfo.Normal.X = (float)pInfo.Normal.X; floatPixelInfo.Normal.Y = (float)pInfo.Normal.Y; floatPixelInfo.Normal.Z = (float)pInfo.Normal.Z; _pictureData.Points[i, j] = floatPixelInfo; } } } }