//Static methods //L2 L3 L4 L5 L6 L7 L8 Ldash D Mdash F xsin xsint xcos xcost ysin ysint ycos ycost zsin zsint zcos zcost //////////////////////////////// Implementation /////////////////////////////// public static C3D EarthVelocity(double JD) { double T = (JD - 2451545) / 36525; double L2 = 3.1761467 + 1021.3285546 * T; double L3 = 1.7534703 + 628.3075849 * T; double L4 = 6.2034809 + 334.0612431 * T; double L5 = 0.5995465 + 52.9690965 * T; double L6 = 0.8740168 + 21.3299095 * T; double L7 = 5.4812939 + 7.4781599 * T; double L8 = 5.3118863 + 3.8133036 * T; double Ldash = 3.8103444 + 8399.6847337 * T; double D = 5.1984667 + 7771.3771486 * T; double Mdash = 2.3555559 + 8328.6914289 * T; double F = 1.6279052 + 8433.4661601 * T; C3D velocity = new C3D(); int nAberrationCoefficients = GFX.g_ACft.Length; for (int i = 0; i < nAberrationCoefficients; i++) { double Argument = GFX.g_ACft[i].L2 * L2 + GFX.g_ACft[i].L3 * L3 + GFX.g_ACft[i].L4 * L4 + GFX.g_ACft[i].L5 * L5 + GFX.g_ACft[i].L6 * L6 + GFX.g_ACft[i].L7 * L7 + GFX.g_ACft[i].L8 * L8 + GFX.g_ACft[i].Ldash * Ldash + GFX.g_ACft[i].D * D + GFX.g_ACft[i].Mdash * Mdash + GFX.g_ACft[i].F * F; velocity.X += (GFX.g_ACft[i].xsin + GFX.g_ACft[i].xsint * T) * Math.Sin(Argument); velocity.X += (GFX.g_ACft[i].xcos + GFX.g_ACft[i].xcost * T) * Math.Cos(Argument); velocity.Y += (GFX.g_ACft[i].ysin + GFX.g_ACft[i].ysint * T) * Math.Sin(Argument); velocity.Y += (GFX.g_ACft[i].ycos + GFX.g_ACft[i].ycost * T) * Math.Cos(Argument); velocity.Z += (GFX.g_ACft[i].zsin + GFX.g_ACft[i].zsint * T) * Math.Sin(Argument); velocity.Z += (GFX.g_ACft[i].zcos + GFX.g_ACft[i].zcost * T) * Math.Cos(Argument); } return(velocity); }
//Static methods //L2 L3 L4 L5 L6 L7 L8 Ldash D Mdash F xsin xsint xcos xcost ysin ysint ycos ycost zsin zsint zcos zcost //////////////////////////////// Implementation /////////////////////////////// public static C3D EarthVelocity(double JD) { double T = (JD - 2451545) / 36525; double L2 = 3.1761467 + 1021.3285546 * T; double L3 = 1.7534703 + 628.3075849 * T; double L4 = 6.2034809 + 334.0612431 * T; double L5 = 0.5995465 + 52.9690965 * T; double L6 = 0.8740168 + 21.3299095 * T; double L7 = 5.4812939 + 7.4781599 * T; double L8 = 5.3118863 + 3.8133036 * T; double Ldash = 3.8103444 + 8399.6847337 * T; double D = 5.1984667 + 7771.3771486 * T; double Mdash = 2.3555559 + 8328.6914289 * T; double F = 1.6279052 + 8433.4661601 * T; C3D velocity = new C3D(); int nAberrationCoefficients = GFX.g_ACft.Length; for (int i =0; i<nAberrationCoefficients; i++) { double Argument = GFX.g_ACft[i].L2 *L2 + GFX.g_ACft[i].L3 *L3 + GFX.g_ACft[i].L4 *L4 + GFX.g_ACft[i].L5 *L5 + GFX.g_ACft[i].L6 *L6 + GFX.g_ACft[i].L7 *L7 + GFX.g_ACft[i].L8 *L8 + GFX.g_ACft[i].Ldash *Ldash + GFX.g_ACft[i].D *D + GFX.g_ACft[i].Mdash *Mdash + GFX.g_ACft[i].F *F; velocity.X += (GFX.g_ACft[i].xsin + GFX.g_ACft[i].xsint * T) * Math.Sin(Argument); velocity.X += (GFX.g_ACft[i].xcos + GFX.g_ACft[i].xcost * T) * Math.Cos(Argument); velocity.Y += (GFX.g_ACft[i].ysin + GFX.g_ACft[i].ysint * T) * Math.Sin(Argument); velocity.Y += (GFX.g_ACft[i].ycos + GFX.g_ACft[i].ycost * T) * Math.Cos(Argument); velocity.Z += (GFX.g_ACft[i].zsin + GFX.g_ACft[i].zsint * T) * Math.Sin(Argument); velocity.Z += (GFX.g_ACft[i].zcos + GFX.g_ACft[i].zcost * T) * Math.Cos(Argument); } return velocity; }
public static C3D EquatorialRectangularCoordinatesAnyEquinox(double JD, double JDEquinox) { C3D @value = EquatorialRectangularCoordinatesJ2000(JD); @value = CAAFK5.ConvertVSOPToFK5AnyEquinox(@value, JDEquinox); return(@value); }
public static C3D EquatorialRectangularCoordinatesB1950(double JD) { C3D @value = EclipticRectangularCoordinatesJ2000(JD); @value = CAAFK5.ConvertVSOPToFK5B1950(@value); return(@value); }
public static C3D ConvertVSOPToFK5J2000(C3D @value) { C3D result = new C3D(); result.X = @value.X + 0.000000440360 * @value.Y - 0.000000190919 * @value.Z; result.Y = -0.000000479966 * @value.X + 0.917482137087 * @value.Y - 0.397776982902 * @value.Z; result.Z = 0.397776982902 * @value.Y + 0.917482137087 * @value.Z; return result; }
public static C3D Create(double x, double y, double z) { C3D item = new C3D(); item.X = x; item.Y = y; item.Z = z; return(item); }
public static C3D Create(double x, double y, double z) { C3D item = new C3D(); item.X = x; item.Y = y; item.Z = z; return item; }
public static C3D ConvertVSOPToFK5B1950(C3D @value) { C3D result = new C3D(); result.X = 0.999925702634 * @value.X + 0.012189716217 * @value.Y + 0.000011134016 * @value.Z; result.Y = -0.011179418036 * @value.X + 0.917413998946 * @value.Y - 0.397777041885 * @value.Z; result.Z = -0.004859003787 * @value.X + 0.397747363646 * @value.Y + 0.917482111428 * @value.Z; return result; }
public static C3D ConvertVSOPToFK5B1950(C3D @value) { C3D result = new C3D(); result.X = 0.999925702634 * @value.X + 0.012189716217 * @value.Y + 0.000011134016 * @value.Z; result.Y = -0.011179418036 * @value.X + 0.917413998946 * @value.Y - 0.397777041885 * @value.Z; result.Z = -0.004859003787 * @value.X + 0.397747363646 * @value.Y + 0.917482111428 * @value.Z; return(result); }
public static C3D ConvertVSOPToFK5J2000(C3D @value) { C3D result = new C3D(); result.X = @value.X + 0.000000440360 * @value.Y - 0.000000190919 * @value.Z; result.Y = -0.000000479966 * @value.X + 0.917482137087 * @value.Y - 0.397776982902 * @value.Z; result.Z = 0.397776982902 * @value.Y + 0.917482137087 * @value.Z; return(result); }
public static C3D EclipticRectangularCoordinatesMeanEquinox(double JD) { double Longitude = CT.D2R(GeometricFK5EclipticLongitude(JD)); double Latitude = CT.D2R(GeometricFK5EclipticLatitude(JD)); double R = CAAEarth.RadiusVector(JD); double epsilon = CT.D2R(CAANutation.MeanObliquityOfEcliptic(JD)); C3D @value = new C3D(); @value.X = R * Math.Cos(Latitude) * Math.Cos(Longitude); @value.Y = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Cos(epsilon) - Math.Sin(Latitude) * Math.Sin(epsilon)); @value.Z = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Sin(epsilon) + Math.Sin(Latitude) * Math.Cos(epsilon)); return @value; }
public static C3D EclipticRectangularCoordinatesMeanEquinox(double JD) { double Longitude = CT.D2R(GeometricFK5EclipticLongitude(JD)); double Latitude = CT.D2R(GeometricFK5EclipticLatitude(JD)); double R = CAAEarth.RadiusVector(JD); double epsilon = CT.D2R(CAANutation.MeanObliquityOfEcliptic(JD)); C3D @value = new C3D(); @value.X = R * Math.Cos(Latitude) * Math.Cos(Longitude); @value.Y = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Cos(epsilon) - Math.Sin(Latitude) * Math.Sin(epsilon)); @value.Z = R * (Math.Cos(Latitude) * Math.Sin(Longitude) * Math.Sin(epsilon) + Math.Sin(Latitude) * Math.Cos(epsilon)); return(@value); }
public static C3D EclipticRectangularCoordinatesJ2000(double JD) { double Longitude = GeometricEclipticLongitudeJ2000(JD); Longitude = CT.D2R(Longitude); double Latitude = GeometricEclipticLatitudeJ2000(JD); Latitude = CT.D2R(Latitude); double R = CAAEarth.RadiusVector(JD); C3D @value = new C3D(); double coslatitude = Math.Cos(Latitude); @value.X = R * coslatitude * Math.Cos(Longitude); @value.Y = R * coslatitude * Math.Sin(Longitude); @value.Z = R * Math.Sin(Latitude); return @value; }
public static C3D ConvertVSOPToFK5AnyEquinox(C3D @value, double JDEquinox) { double t = (JDEquinox - 2451545.0) / 36525; double tsquared = t * t; double tcubed = tsquared * t; double sigma = 2306.2181 * t + 0.30188 * tsquared + 0.017988 * tcubed; sigma = CT.D2R(CT.DMS2D(0, 0, sigma)); double zeta = 2306.2181 * t + 1.09468 * tsquared + 0.018203 * tcubed; zeta = CT.D2R(CT.DMS2D(0, 0, zeta)); double phi = 2004.3109 * t - 0.42665 * tsquared - 0.041833 * tcubed; phi = CT.D2R(CT.DMS2D(0, 0, phi)); double cossigma = Math.Cos(sigma); double coszeta = Math.Cos(zeta); double cosphi = Math.Cos(phi); double sinsigma = Math.Sin(sigma); double sinzeta = Math.Sin(zeta); double sinphi = Math.Sin(phi); double xx = cossigma * coszeta * cosphi - sinsigma * sinzeta; double xy = sinsigma * coszeta + cossigma * sinzeta * cosphi; double xz = cossigma * sinphi; double yx = -cossigma * sinzeta - sinsigma * coszeta * cosphi; double yy = cossigma * coszeta - sinsigma * sinzeta * cosphi; double yz = -sinsigma * sinphi; double zx = -coszeta * sinphi; double zy = -sinzeta * sinphi; double zz = cosphi; C3D result = new C3D(); result.X = xx * @value.X + yx * @value.Y + zx * @value.Z; result.Y = xy * @value.X + yy * @value.Y + zy * @value.Z; result.Z = xz * @value.X + yz * @value.Y + zz * @value.Z; return(result); }
public static C3D EclipticRectangularCoordinatesJ2000(double JD) { double Longitude = GeometricEclipticLongitudeJ2000(JD); Longitude = CT.D2R(Longitude); double Latitude = GeometricEclipticLatitudeJ2000(JD); Latitude = CT.D2R(Latitude); double R = CAAEarth.RadiusVector(JD); C3D @value = new C3D(); double coslatitude = Math.Cos(Latitude); @value.X = R * coslatitude * Math.Cos(Longitude); @value.Y = R * coslatitude * Math.Sin(Longitude); @value.Z = R * Math.Sin(Latitude); return(@value); }
public static COR EquatorialAberration(double Alpha, double Delta, double JD) { //Convert to radians Alpha = CT.D2R(Alpha * 15); Delta = CT.D2R(Delta); double cosAlpha = Math.Cos(Alpha); double sinAlpha = Math.Sin(Alpha); double cosDelta = Math.Cos(Delta); double sinDelta = Math.Sin(Delta); C3D velocity = EarthVelocity(JD); //What is the return value COR aberration = new COR(); aberration.X = CT.R2H((velocity.Y * cosAlpha - velocity.X * sinAlpha) / (17314463350.0 * cosDelta)); aberration.Y = CT.R2D(-(((velocity.X * cosAlpha + velocity.Y * sinAlpha) * sinDelta - velocity.Z * cosDelta) / 17314463350.0)); return(aberration); }
public static C3D ConvertVSOPToFK5AnyEquinox(C3D @value, double JDEquinox) { double t = (JDEquinox - 2451545.0) / 36525; double tsquared = t *t; double tcubed = tsquared * t; double sigma = 2306.2181 *t + 0.30188 *tsquared + 0.017988 *tcubed; sigma = CT.D2R(CT.DMS2D(0, 0, sigma)); double zeta = 2306.2181 *t + 1.09468 *tsquared + 0.018203 *tcubed; zeta = CT.D2R(CT.DMS2D(0, 0, zeta)); double phi = 2004.3109 *t - 0.42665 *tsquared - 0.041833 *tcubed; phi = CT.D2R(CT.DMS2D(0, 0, phi)); double cossigma = Math.Cos(sigma); double coszeta = Math.Cos(zeta); double cosphi = Math.Cos(phi); double sinsigma = Math.Sin(sigma); double sinzeta = Math.Sin(zeta); double sinphi = Math.Sin(phi); double xx = cossigma * coszeta * cosphi -sinsigma *sinzeta; double xy = sinsigma * coszeta + cossigma * sinzeta * cosphi; double xz = cossigma * sinphi; double yx = -cossigma * sinzeta - sinsigma * coszeta * cosphi; double yy = cossigma * coszeta - sinsigma * sinzeta * cosphi; double yz = -sinsigma * sinphi; double zx = -coszeta * sinphi; double zy = -sinzeta * sinphi; double zz = cosphi; C3D result = new C3D(); result.X = xx * @value.X + yx * @value.Y + zx * @value.Z; result.Y = xy * @value.X + yy * @value.Y + zy * @value.Z; result.Z = xz * @value.X + yz * @value.Y + zz * @value.Z; return result; }
// ReSharper disable once InconsistentNaming // data is object[] { bool exportAttachments, string materialReference, string modelName, bool onlyOneLOD, bool skipCollision } public void Write(ICLIFlags flags, Chunked chunked, Stream output, List <byte> LODs, object[] data, FindLogic.Combo.ModelInfoNew modelInfo) { byte?flagLOD = null; if (flags is ExtractFlags extractFlags) { flagLOD = extractFlags.LOD; } IChunk chunk = chunked.FindNextChunk("MNRM").Value; if (chunk == null) { return; } MNRM model = (MNRM)chunk; chunk = chunked.FindNextChunk("CLDM").Value; CLDM materials = null; if (chunk != null) { materials = (CLDM)chunk; } chunk = chunked.FindNextChunk("lksm").Value; lksm skeleton = null; if (chunk != null) { skeleton = (lksm)chunk; } chunk = chunked.FindNextChunk("PRHM").Value; PRHM hardpoints = null; if (chunk != null) { hardpoints = (PRHM)chunk; } HTLC cloth = chunked.FindNextChunk("HTLC").Value as HTLC; short[] hierarchy = (short[])skeleton?.Hierarchy.Clone(); Dictionary <int, HTLC.ClothNode> nodeMap = new Dictionary <int, HTLC.ClothNode>(); if (cloth != null) { uint clothIndex = 0; foreach (HTLC.ClothNode[] nodeCollection in cloth.Nodes) { if (nodeCollection == null) { continue; } int nodeIndex = 0; foreach (HTLC.ClothNode node in nodeCollection) { int parentRaw = node.VerticalParent; if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex) && cloth.NodeBones[clothIndex].ContainsKey(parentRaw)) { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = cloth.NodeBones[clothIndex][parentRaw]; if (cloth.NodeBones[clothIndex][parentRaw] == -1) { HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; } } } else { if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = -1; HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; } } } if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { nodeMap[cloth.NodeBones[clothIndex][nodeIndex]] = node; } } nodeIndex++; } clothIndex++; } } using (BinaryWriter writer = new BinaryWriter(output)) { writer.Write((ushort)1); // version major writer.Write((ushort)5); // version minor if (data.Length > 1 && data[1] is string && ((string)data[1]).Length > 0) { writer.Write((string)data[1]); } else { writer.Write((byte)0); } if (data.Length > 2 && data[2] is string && ((string)data[2]).Length > 0) { writer.Write((string)data[2]); } else { writer.Write((byte)0); } if (skeleton == null) { writer.Write((ushort)0); // number of bones } else { writer.Write(skeleton.Data.bonesAbs); } // ReSharper disable once InconsistentNaming Dictionary <byte, List <int> > LODMap = new Dictionary <byte, List <int> >(); uint sz = 0; uint lookForLod = 0; if (model.Submeshes.Any(x => x.lod == flagLOD)) { lookForLod = (byte)flagLOD; } else if (flagLOD != null) { SubmeshDescriptor nextLowest = model.Submeshes.Where(p => p.lod < flagLOD).OrderBy(x => x.lod).LastOrDefault(); if (nextLowest.verticesToDraw == 0 && nextLowest.indexCount == 0) // not real mesh { SubmeshDescriptor nextHighest = model.Submeshes.Where(p => p.lod > flagLOD).OrderBy(x => x.lod).FirstOrDefault(); lookForLod = nextHighest.lod; } else { lookForLod = nextLowest.lod; } } for (int i = 0; i < model.Submeshes.Length; ++i) { SubmeshDescriptor submesh = model.Submeshes[i]; if (data.Length > 4 && data[4] is bool && (bool)data[4]) { if (submesh.flags == SubmeshFlags.COLLISION_MESH) { continue; } } if (lookForLod > 0 && submesh.lod != lookForLod && submesh.lod != 255) { continue; } if (!LODMap.ContainsKey(submesh.lod)) { LODMap.Add(submesh.lod, new List <int>()); } sz++; LODMap[submesh.lod].Add(i); } writer.Write(sz); writer.Write(hardpoints?.HardPoints.Length ?? 0); if (skeleton != null) { for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { writer.Write(IdToString("bone", skeleton.IDs[i])); short parent = hierarchy[i]; if (parent == -1) { parent = (short)i; } writer.Write(parent); Matrix3x4 bone = skeleton.Matrices34[i]; Quaternion rot = new Quaternion(bone[0, 0], bone[0, 1], bone[0, 2], bone[0, 3]); Vector3 scl = new Vector3(bone[1, 0], bone[1, 1], bone[1, 2]); Vector3 pos = new Vector3(bone[2, 0], bone[2, 1], bone[2, 2]); if (nodeMap.ContainsKey(i)) { HTLC.ClothNode thisNode = nodeMap[i]; pos.X = thisNode.X; pos.Y = thisNode.Y; pos.Z = thisNode.Z; } writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(scl.X); writer.Write(scl.Y); writer.Write(scl.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); writer.Write(rot.W); } } foreach (KeyValuePair <byte, List <int> > kv in LODMap) { foreach (int i in kv.Value) { SubmeshDescriptor submesh = model.Submeshes[i]; ModelVertex[] vertex = model.Vertices[i]; ModelVertex[] normal = model.Normals[i]; ModelUV[][] uv = model.TextureCoordinates[i]; ModelIndice[] index = model.Indices[i]; ModelBoneData[] bones = model.Bones[i]; writer.Write($"Submesh_{i}.{kv.Key}.{materials.Materials[submesh.material]:X16}"); writer.Write(materials.Materials[submesh.material]); writer.Write((byte)uv.Length); writer.Write(vertex.Length); writer.Write(index.Length); for (int j = 0; j < vertex.Length; ++j) { writer.Write(vertex[j].x); writer.Write(vertex[j].y); writer.Write(vertex[j].z); writer.Write(-normal[j].x); writer.Write(-normal[j].y); writer.Write(-normal[j].z); foreach (ModelUV[] t in uv) { writer.Write(t[j].u); writer.Write(t[j].v); } if (skeleton != null && bones != null && bones[j].boneIndex != null && bones[j].boneWeight != null) { writer.Write((byte)4); writer.Write(skeleton.Lookup[bones[j].boneIndex[0]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[1]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[2]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[3]]); writer.Write(bones[j].boneWeight[0]); writer.Write(bones[j].boneWeight[1]); writer.Write(bones[j].boneWeight[2]); writer.Write(bones[j].boneWeight[3]); } else { // bone -> size + index + weight writer.Write((byte)0); } } List <ModelIndiceModifiable> indexNew = new List <ModelIndiceModifiable>(); foreach (ModelIndice indice in index) { indexNew.Add(new ModelIndiceModifiable { v1 = indice.v1, v2 = indice.v2, v3 = indice.v3 }); } foreach (ModelIndiceModifiable indice in indexNew) { writer.Write((byte)3); writer.Write(indice.v1); writer.Write(indice.v2); writer.Write(indice.v3); } } } if (hardpoints != null) { // attachments foreach (PRHM.HardPoint hp in hardpoints.HardPoints) { writer.Write(IdToString("hardpoint", GUID.Index(hp.HardPointGUID))); Matrix4 mat = hp.Matrix.ToOpenTK(); Vector3 pos = mat.ExtractTranslation(); Quaternion rot = mat.ExtractRotation(); writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); writer.Write(rot.W); } // extension 1.1 foreach (PRHM.HardPoint hp in hardpoints.HardPoints) { writer.Write(IdToString("bone", GUID.Index(hp.GUIDx012))); } } // ext 1.3: cloth writer.Write(0); // ext 1.4: embedded refpose if (skeleton != null) { for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { writer.Write(IdToString("bone", skeleton.IDs[i])); short parent = hierarchy[i]; writer.Write(parent); Matrix3x4 bone = skeleton.Matrices34Inverted[i]; Quaternion3D quat = new Quaternion3D(bone[0, 3], bone[0, 0], bone[0, 1], bone[0, 2]); Vector3D rot = C3D.ToEulerAngles(quat); // ReSharper disable CompareOfFloatsByEqualityOperator if (rot.X == -3.14159274f && rot.Y == 0 && rot.Z == 0) { rot = new Vector3D(0, 3.14159274f, 3.14159274f); // effectively the same but you know, eulers. } // ReSharper restore CompareOfFloatsByEqualityOperator Vector3 scl = new Vector3(bone[1, 0], bone[1, 1], bone[1, 2]); Vector3 pos = new Vector3(bone[2, 0], bone[2, 1], bone[2, 2]); writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(scl.X); writer.Write(scl.Y); writer.Write(scl.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); } } // ext 1.5: guid writer.Write(GUID.Index(modelInfo.GUID)); // ext 1.6: cloth 2.0 if (cloth == null) { writer.Write(0); } else { writer.Write(cloth.Descriptors.Length); for (int i = 0; i < cloth.Descriptors.Length; i++) { var desc = cloth.Descriptors[i]; writer.Write(desc.Name); writer.Write(cloth.Nodes[i].Length); foreach (HTLC.ClothNode clothNode in cloth.Nodes[i]) { writer.Write(clothNode.Bones.Length); foreach (HTLC.ClothNodeWeight clothNodeWeight in clothNode.Bones) { writer.Write(clothNodeWeight.Bone); writer.Write(clothNodeWeight.Weight); } } } } } }
public static CAAParabolicObjectDetails Calculate(double JD, CAAParabolicObjectElements elements) { double Epsilon = CAANutation.MeanObliquityOfEcliptic(elements.JDEquinox); double JD0 = JD; //What will be the return value CAAParabolicObjectDetails details = new CAAParabolicObjectDetails(); Epsilon = CT.D2R(Epsilon); double omega = CT.D2R(elements.omega); double w = CT.D2R(elements.w); double i = CT.D2R(elements.i); double sinEpsilon = Math.Sin(Epsilon); double cosEpsilon = Math.Cos(Epsilon); double sinOmega = Math.Sin(omega); double cosOmega = Math.Cos(omega); double cosi = Math.Cos(i); double sini = Math.Sin(i); double F = cosOmega; double G = sinOmega * cosEpsilon; double H = sinOmega * sinEpsilon; double P = -sinOmega * cosi; double Q = cosOmega * cosi * cosEpsilon - sini * sinEpsilon; double R = cosOmega * cosi * sinEpsilon + sini * cosEpsilon; double a = Math.Sqrt(F * F + P * P); double b = Math.Sqrt(G * G + Q * Q); double c = Math.Sqrt(H * H + R * R); double A = Math.Atan2(F, P); double B = Math.Atan2(G, Q); double C = Math.Atan2(H, R); C3D SunCoord = CAASun.EquatorialRectangularCoordinatesAnyEquinox(JD, elements.JDEquinox); for (int j = 0; j < 2; j++) { double W = 0.03649116245 / (elements.q * Math.Sqrt(elements.q)) * (JD0 - elements.T); double s = CalculateBarkers(W); double v = 2 * Math.Atan(s); double r = elements.q * (1 + s * s); double x = r * a * Math.Sin(A + w + v); double y = r * b * Math.Sin(B + w + v); double z = r * c * Math.Sin(C + w + v); if (j == 0) { details.HeliocentricRectangularEquatorial.X = x; details.HeliocentricRectangularEquatorial.Y = y; details.HeliocentricRectangularEquatorial.Z = z; //Calculate the heliocentric ecliptic coordinates also double u = omega + v; double cosu = Math.Cos(u); double sinu = Math.Sin(u); details.HeliocentricRectangularEcliptical.X = r * (cosOmega * cosu - sinOmega * sinu * cosi); details.HeliocentricRectangularEcliptical.Y = r * (sinOmega * cosu + cosOmega * sinu * cosi); details.HeliocentricRectangularEcliptical.Z = r * sini * sinu; details.HeliocentricEclipticLongitude = Math.Atan2(y, x); details.HeliocentricEclipticLongitude = CT.M24(CT.R2D(details.HeliocentricEclipticLongitude) / 15); details.HeliocentricEclipticLatitude = Math.Asin(z / r); details.HeliocentricEclipticLatitude = CT.R2D(details.HeliocentricEclipticLatitude); } double psi = SunCoord.X + x; double nu = SunCoord.Y + y; double sigma = SunCoord.Z + z; double Alpha = Math.Atan2(nu, psi); Alpha = CT.R2D(Alpha); double Delta = Math.Atan2(sigma, Math.Sqrt(psi * psi + nu * nu)); Delta = CT.R2D(Delta); double Distance = Math.Sqrt(psi * psi + nu * nu + sigma * sigma); if (j == 0) { details.TrueGeocentricRA = CT.M24(Alpha / 15); details.TrueGeocentricDeclination = Delta; details.TrueGeocentricDistance = Distance; details.TrueGeocentricLightTime = ELL.DistanceToLightTime(Distance); } else { details.AstrometricGeocenticRA = CT.M24(Alpha / 15); details.AstrometricGeocentricDeclination = Delta; details.AstrometricGeocentricDistance = Distance; details.AstrometricGeocentricLightTime = ELL.DistanceToLightTime(Distance); double RES = Math.Sqrt(SunCoord.X * SunCoord.X + SunCoord.Y * SunCoord.Y + SunCoord.Z * SunCoord.Z); details.Elongation = CT.R2D(Math.Acos((RES * RES + Distance * Distance - r * r) / (2 * RES * Distance))); details.PhaseAngle = CT.R2D(Math.Acos((r * r + Distance * Distance - RES * RES) / (2 * r * Distance))); } if (j == 0) //Prepare for the next loop around { JD0 = JD - details.TrueGeocentricLightTime; } } return(details); }
public static void ConvertAnimation(string refpose, string input, string output) { NumberFormatInfo format = new NumberFormatInfo(); format.NumberDecimalSeparator = "."; StreamReader refpose_reader = new StreamReader(refpose); int refpose_bonecount = Convert.ToInt32(refpose_reader.ReadLine()); Dictionary <int, int> refpose_parentmap = new Dictionary <int, int>(); Dictionary <int, int> refpose_indexmap = new Dictionary <int, int>(); int[] refpose_bonearray = new int[refpose_bonecount]; int[] refpose_hierarchy = new int[refpose_bonecount]; refpose_reader.ReadLine(); refpose_reader.ReadLine(); for (int index = 0; index < refpose_bonecount; ++index) { string[] array = refpose_reader.ReadLine().Replace("\"", string.Empty).Split(' '); refpose_bonearray[index] = Convert.ToInt32(array[1].Split('_').Last(), 16); refpose_hierarchy[index] = Convert.ToInt32(array[2]); } for (int index = 0; index < refpose_bonecount; ++index) { if (refpose_hierarchy[index] != -1) { refpose_parentmap.Add(refpose_bonearray[index], refpose_bonearray[refpose_hierarchy[index]]); } else { refpose_parentmap.Add(refpose_bonearray[index], -1); } refpose_indexmap.Add(refpose_bonearray[index], index); } refpose_reader.ReadLine(); refpose_reader.ReadLine(); refpose_reader.ReadLine(); Vector3D[] refpose_position = new Vector3D[refpose_bonecount]; Vector3D[] refpose_rotation = new Vector3D[refpose_bonecount]; Vector3D[] refpose_scale = new Vector3D[refpose_bonecount]; for (int index = 0; index < refpose_bonecount; ++index) { refpose_position[index] = new Vector3D(); refpose_rotation[index] = new Vector3D(); refpose_scale[index] = new Vector3D(1, 1, 1); string[] array = refpose_reader.ReadLine().Replace("\"", string.Empty).Split(' '); refpose_position[index].X = Convert.ToSingle(array[2], format); refpose_position[index].Y = Convert.ToSingle(array[3], format); refpose_position[index].Z = Convert.ToSingle(array[4], format); refpose_rotation[index].X = Convert.ToSingle(array[6], format); refpose_rotation[index].Y = Convert.ToSingle(array[7], format); refpose_rotation[index].Z = Convert.ToSingle(array[8], format); } refpose_reader.Close(); FileStream inputStream = new FileStream(input, FileMode.Open); BinaryReader input_reader = new BinaryReader(inputStream); input_reader.ReadInt32(); float duration = input_reader.ReadSingle(); float fps = input_reader.ReadSingle(); ushort bone_count = input_reader.ReadUInt16(); input_reader.ReadUInt16(); int frame_count = (int)(fps * (double)duration) + 1; inputStream.Seek(24L, SeekOrigin.Current); long offset_bone_list = input_reader.ReadInt64(); long offset_info_table = input_reader.ReadInt64(); inputStream.Seek(24L, SeekOrigin.Current); StreamWriter output_writer = new StreamWriter(output); output_writer.WriteLine("version 1"); output_writer.WriteLine("nodes"); int[] bone_list = new int[bone_count]; inputStream.Seek(offset_bone_list, SeekOrigin.Begin); Dictionary <int, int> bone_translation_map = new Dictionary <int, int>(); int bone_id; for (int index = 0; index < bone_count; ++index) { bone_id = input_reader.ReadInt32(); bone_list[index] = bone_id; bone_translation_map.Add(bone_id, index); } for (int index = 0; index < bone_count; ++index) { bone_id = bone_list[index]; int num3 = -1; if (refpose_parentmap.ContainsKey(bone_id)) { int key2 = refpose_parentmap[bone_id]; num3 = !bone_translation_map.ContainsKey(key2) ? -1 : bone_translation_map[key2]; } output_writer.WriteLine(index.ToString() + " \"bone_" + bone_id.ToString("X4") + "\" " + num3); } int last_bone_index = bone_count; Dictionary <int, int> secondary_bone_translation_map = new Dictionary <int, int>(); for (int index = 0; index < refpose_bonecount; ++index) { if (!bone_translation_map.ContainsKey(refpose_bonearray[index])) { secondary_bone_translation_map.Add(refpose_bonearray[index], last_bone_index); } } for (int index = 0; index < refpose_bonecount; ++index) { if (!bone_translation_map.ContainsKey(refpose_bonearray[index])) { int key2 = refpose_parentmap[refpose_bonearray[index]]; int num3 = !bone_translation_map.ContainsKey(key2) ? (!secondary_bone_translation_map.ContainsKey(key2) ? -1 : secondary_bone_translation_map[key2]) : bone_translation_map[key2]; output_writer.WriteLine(last_bone_index.ToString() + " \"bone_" + refpose_bonearray[index].ToString("X4") + "\" " + num3); ++last_bone_index; } } output_writer.WriteLine("end"); float[,] x_array = new float[last_bone_index, frame_count]; float[,] y_array = new float[last_bone_index, frame_count]; float[,] z_array = new float[last_bone_index, frame_count]; float[,] sx_array = new float[last_bone_index, frame_count]; float[,] sy_array = new float[last_bone_index, frame_count]; float[,] sz_array = new float[last_bone_index, frame_count]; float[,] rx_array = new float[last_bone_index, frame_count]; float[,] ry_array = new float[last_bone_index, frame_count]; float[,] rz_array = new float[last_bone_index, frame_count]; float[,] rw_array = new float[last_bone_index, frame_count]; bool[,] has_rotation_frame = new bool[last_bone_index, frame_count]; bool[,] has_position_frame = new bool[last_bone_index, frame_count]; bool[,] has_scale_frame = new bool[last_bone_index, frame_count]; output_writer.WriteLine("skeleton"); output_writer.WriteLine("time 0"); for (int index = 0; index < bone_count; ++index) { if (refpose_indexmap.ContainsKey(bone_list[index])) { bone_id = refpose_indexmap[bone_list[index]]; output_writer.Write(index); output_writer.Write(" " + refpose_position[bone_id].X.ToString("0.000000", format)); output_writer.Write(" " + refpose_position[bone_id].Y.ToString("0.000000", format)); output_writer.Write(" " + refpose_position[bone_id].Z.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[bone_id].X.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[bone_id].Y.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[bone_id].Z.ToString("0.000000", format)); output_writer.WriteLine(); } else { output_writer.WriteLine(index.ToString() + " 0 0 0 0 0 0"); } } int num4 = bone_count; for (int index = 0; index < refpose_bonecount; ++index) { if (!bone_translation_map.ContainsKey(refpose_bonearray[index])) { output_writer.Write(num4++); output_writer.Write(" " + refpose_position[index].X.ToString("0.000000", format)); output_writer.Write(" " + refpose_position[index].Y.ToString("0.000000", format)); output_writer.Write(" " + refpose_position[index].Z.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[index].X.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[index].Y.ToString("0.000000", format)); output_writer.Write(" " + refpose_rotation[index].Z.ToString("0.000000", format)); output_writer.WriteLine(); } } Quaternion3D q = new Quaternion3D(); Vector3D vector3D = new Vector3D(); inputStream.Seek(offset_info_table, SeekOrigin.Begin); for (int index1 = 0; index1 < bone_count; ++index1) { long position = inputStream.Position; int scale_count = input_reader.ReadInt16(); int position_count = input_reader.ReadInt16(); int rotation_count = input_reader.ReadInt16(); int flags = input_reader.ReadInt16(); long scale_indices_offset = input_reader.ReadInt32() * 4 + position; long position_indices_offset = input_reader.ReadInt32() * 4 + position; long rotation_indices_offset = input_reader.ReadInt32() * 4 + position; long scale_data_offset = input_reader.ReadInt32() * 4 + position; long position_data_offset = input_reader.ReadInt32() * 4 + position; long rotation_data_offset = input_reader.ReadInt32() * 4 + position; int[] scale_indices = new int[scale_count]; inputStream.Seek(scale_indices_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < scale_count; ++index2) { scale_indices[index2] = frame_count > byte.MaxValue ? input_reader.ReadInt16() : input_reader.ReadByte(); } inputStream.Seek(scale_data_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < scale_count; ++index2) { int index3 = scale_indices[index2]; has_scale_frame[index1, index3] = true; float x = input_reader.ReadUInt16() / 1024.0f; sx_array[index1, index3] = x; float y = input_reader.ReadUInt16() / 1024.0f; sy_array[index1, index3] = y; float z = input_reader.ReadUInt16() / 1024.0f; sz_array[index1, index3] = z; } int[] position_indices = new int[position_count]; inputStream.Seek(position_indices_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < position_count; ++index2) { position_indices[index2] = frame_count > byte.MaxValue ? input_reader.ReadInt16() : input_reader.ReadByte(); } inputStream.Seek(position_data_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < position_count; ++index2) { int index3 = position_indices[index2]; has_position_frame[index1, index3] = true; float x = input_reader.ReadSingle(); x_array[index1, index3] = x; float y = input_reader.ReadSingle(); y_array[index1, index3] = y; float z = input_reader.ReadSingle(); z_array[index1, index3] = z; } int[] rotation_indices = new int[rotation_count]; inputStream.Seek(rotation_indices_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < rotation_count; ++index2) { rotation_indices[index2] = frame_count > byte.MaxValue ? input_reader.ReadInt16() : input_reader.ReadByte(); } inputStream.Seek(rotation_data_offset, SeekOrigin.Begin); for (int index2 = 0; index2 < rotation_count; ++index2) { ushort rot_a = input_reader.ReadUInt16(); ushort rot_b = input_reader.ReadUInt16(); ushort rot_c = input_reader.ReadUInt16(); Vec4d rot = Animation.UnpackRotation(rot_a, rot_b, rot_c); int index3 = rotation_indices[index2]; has_rotation_frame[index1, index3] = true; rx_array[index1, index3] = (float)rot.x; ry_array[index1, index3] = (float)rot.y; rz_array[index1, index3] = (float)rot.z; rw_array[index1, index3] = (float)rot.w; } inputStream.Seek(position + 32L, SeekOrigin.Begin); } for (int index1 = 0; index1 < frame_count; ++index1) { output_writer.WriteLine($"time {index1 + 1}"); for (int index2 = 0; index2 < last_bone_index; ++index2) { if (has_position_frame[index2, index1] || has_rotation_frame[index2, index1] || has_scale_frame[index2, index1]) { if (!has_position_frame[index2, index1]) { int index3 = index1; int index4 = index1; while (!has_position_frame[index2, index3]) { --index3; } while (index4 < frame_count && !has_position_frame[index2, index4]) { ++index4; } if (index4 == frame_count) { x_array[index2, index1] = x_array[index2, index3]; y_array[index2, index1] = y_array[index2, index3]; z_array[index2, index1] = z_array[index2, index3]; } else { float num3 = (index1 - index3) / (float)(index4 - index3); x_array[index2, index1] = (x_array[index2, index4] - x_array[index2, index3]) * num3 + x_array[index2, index3]; y_array[index2, index1] = (y_array[index2, index4] - y_array[index2, index3]) * num3 + y_array[index2, index3]; z_array[index2, index1] = (z_array[index2, index4] - z_array[index2, index3]) * num3 + z_array[index2, index3]; } } if (!has_scale_frame[index2, index1]) { int index3 = index1; int index4 = index1; while (!has_scale_frame[index2, index3]) { --index3; } while (index4 < frame_count && !has_scale_frame[index2, index4]) { ++index4; } if (index4 == frame_count) { sx_array[index2, index1] = sx_array[index2, index3]; sy_array[index2, index1] = sy_array[index2, index3]; sz_array[index2, index1] = sz_array[index2, index3]; } else { float num3 = (index1 - index3) / (float)(index4 - index3); sx_array[index2, index1] = (sx_array[index2, index4] - sx_array[index2, index3]) * num3 + sx_array[index2, index3]; sy_array[index2, index1] = (sy_array[index2, index4] - sy_array[index2, index3]) * num3 + sy_array[index2, index3]; sz_array[index2, index1] = (sz_array[index2, index4] - sz_array[index2, index3]) * num3 + sz_array[index2, index3]; } } if (!has_rotation_frame[index2, index1]) { int index3 = index1; int index4 = index1; while (!has_rotation_frame[index2, index3]) { --index3; } while (index4 < frame_count && !has_rotation_frame[index2, index4]) { ++index4; } if (index4 == frame_count) { rx_array[index2, index1] = rx_array[index2, index3]; ry_array[index2, index1] = ry_array[index2, index3]; rz_array[index2, index1] = rz_array[index2, index3]; rw_array[index2, index1] = rw_array[index2, index3]; } else { double num3 = rx_array[index2, index4] * (double)rx_array[index2, index3] + ry_array[index2, index4] * (double)ry_array[index2, index3] + rz_array[index2, index4] * (double)rz_array[index2, index3] + rw_array[index2, index4] * (double)rw_array[index2, index3]; float num9 = (index1 - index3) / (float)(index4 - index3); if (num3 < 0.0) { rx_array[index2, index1] = (-rx_array[index2, index4] - rx_array[index2, index3]) * num9 + rx_array[index2, index3]; ry_array[index2, index1] = (-ry_array[index2, index4] - ry_array[index2, index3]) * num9 + ry_array[index2, index3]; rz_array[index2, index1] = (-rz_array[index2, index4] - rz_array[index2, index3]) * num9 + rz_array[index2, index3]; rw_array[index2, index1] = (-rw_array[index2, index4] - rw_array[index2, index3]) * num9 + rw_array[index2, index3]; } else { rx_array[index2, index1] = (rx_array[index2, index4] - rx_array[index2, index3]) * num9 + rx_array[index2, index3]; ry_array[index2, index1] = (ry_array[index2, index4] - ry_array[index2, index3]) * num9 + ry_array[index2, index3]; rz_array[index2, index1] = (rz_array[index2, index4] - rz_array[index2, index3]) * num9 + rz_array[index2, index3]; rw_array[index2, index1] = (rw_array[index2, index4] - rw_array[index2, index3]) * num9 + rw_array[index2, index3]; } } } output_writer.Write(index2); output_writer.Write(" " + x_array[index2, index1].ToString("0.000000", format)); output_writer.Write(" " + y_array[index2, index1].ToString("0.000000", format)); output_writer.Write(" " + z_array[index2, index1].ToString("0.000000", format)); q.i = rx_array[index2, index1]; q.j = ry_array[index2, index1]; q.k = rz_array[index2, index1]; q.real = rw_array[index2, index1]; Vector3D eulerAngles = C3D.ToEulerAngles(q); output_writer.Write(" " + eulerAngles.X.ToString("0.000000", format)); output_writer.Write(" " + eulerAngles.Y.ToString("0.000000", format)); output_writer.Write(" " + eulerAngles.Z.ToString("0.000000", format)); output_writer.WriteLine(); } } } output_writer.WriteLine("end"); output_writer.Close(); }
// ReSharper disable once InconsistentNaming public bool Write(Chunked chunked, Stream output, List <byte> LODs, Dictionary <ulong, List <ImageLayer> > layers, object[] data) { IChunk chunk = chunked.FindNextChunk("MNRM").Value; if (chunk == null) { return(false); } MNRM model = (MNRM)chunk; chunk = chunked.FindNextChunk("CLDM").Value; CLDM materials = null; if (chunk != null) { materials = (CLDM)chunk; } chunk = chunked.FindNextChunk("lksm").Value; lksm skeleton = null; if (chunk != null) { skeleton = (lksm)chunk; } chunk = chunked.FindNextChunk("PRHM").Value; PRHM hardpoints = null; if (chunk != null) { hardpoints = (PRHM)chunk; } short[] hierarchy = (short[])skeleton?.Hierarchy.Clone(); Dictionary <int, HTLC.ClothNode> nodeMap = new Dictionary <int, HTLC.ClothNode>(); if (chunked.FindNextChunk("HTLC").Value is HTLC cloth) { uint clothIndex = 0; foreach (HTLC.ClothNode[] nodeCollection in cloth.Nodes) { if (nodeCollection == null) { continue; } int nodeIndex = 0; foreach (HTLC.ClothNode node in nodeCollection) { int parentRaw = node.VerticalParent; if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex) && cloth.NodeBones[clothIndex].ContainsKey(parentRaw)) { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = cloth.NodeBones[clothIndex][parentRaw]; if (cloth.NodeBones[clothIndex][parentRaw] == -1) { HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; } } } else { if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) // if on main skele { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = -1; HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; } } } if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) { // good code: if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { nodeMap[cloth.NodeBones[clothIndex][nodeIndex]] = node; } } nodeIndex++; } clothIndex++; } } using (BinaryWriter writer = new BinaryWriter(output)) { writer.Write((ushort)1); // version major writer.Write((ushort)4); // version minor if (data.Length > 1 && data[1] is string && ((string)data[1]).Length > 0) { writer.Write((string)data[1]); } else { writer.Write((byte)0); } if (data.Length > 2 && data[2] is string && ((string)data[2]).Length > 0) { writer.Write((string)data[2]); } else { writer.Write((byte)0); } if (skeleton == null) { writer.Write((ushort)0); // number of bones } else { writer.Write(skeleton.Data.bonesAbs); } // ReSharper disable once InconsistentNaming Dictionary <byte, List <int> > LODMap = new Dictionary <byte, List <int> >(); uint sz = 0; uint lookForLod = 0; bool lodOnly = data.Length > 3 && data[3] is bool && (bool)data[3]; for (int i = 0; i < model.Submeshes.Length; ++i) { SubmeshDescriptor submesh = model.Submeshes[i]; if (data.Length > 4 && data[4] is bool && (bool)data[4]) { if (submesh.flags == SubmeshFlags.COLLISION_MESH) { continue; } } if (LODs != null && !LODs.Contains(submesh.lod)) { continue; } if (lodOnly && lookForLod > 0 && submesh.lod != lookForLod) { continue; } if (!LODMap.ContainsKey(submesh.lod)) { LODMap.Add(submesh.lod, new List <int>()); } lookForLod = submesh.lod; sz++; LODMap[submesh.lod].Add(i); } //long meshCountPos = writer.BaseStream.Position; writer.Write(sz); writer.Write(hardpoints?.HardPoints.Length ?? 0); if (skeleton != null) { for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { writer.Write(IdToString("bone", skeleton.IDs[i])); short parent = hierarchy[i]; if (parent == -1) { parent = (short)i; } writer.Write(parent); Matrix3x4 bone = skeleton.Matrices34[i]; Quaternion rot = new Quaternion(bone[0, 0], bone[0, 1], bone[0, 2], bone[0, 3]); Vector3 scl = new Vector3(bone[1, 0], bone[1, 1], bone[1, 2]); Vector3 pos = new Vector3(bone[2, 0], bone[2, 1], bone[2, 2]); if (nodeMap.ContainsKey(i)) { HTLC.ClothNode thisNode = nodeMap[i]; pos.X = thisNode.X; pos.Y = thisNode.Y; pos.Z = thisNode.Z; } writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(scl.X); writer.Write(scl.Y); writer.Write(scl.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); writer.Write(rot.W); } } foreach (KeyValuePair <byte, List <int> > kv in LODMap) { foreach (int i in kv.Value) { SubmeshDescriptor submesh = model.Submeshes[i]; ModelVertex[] vertex = model.Vertices[i]; ModelVertex[] normal = model.Normals[i]; ModelUV[][] uv = model.TextureCoordinates[i]; ModelIndice[] index = model.Indices[i]; ModelBoneData[] bones = model.Bones[i]; writer.Write($"Submesh_{i}.{kv.Key}.{materials.Materials[submesh.material]:X16}"); writer.Write(materials.Materials[submesh.material]); writer.Write((byte)uv.Length); writer.Write(vertex.Length); writer.Write(index.Length); for (int j = 0; j < vertex.Length; ++j) { writer.Write(vertex[j].x); writer.Write(vertex[j].y); writer.Write(vertex[j].z); writer.Write(-normal[j].x); writer.Write(-normal[j].y); writer.Write(-normal[j].z); foreach (ModelUV[] t in uv) { writer.Write(t[j].u); writer.Write(t[j].v); } if (skeleton != null && bones != null && bones[j].boneIndex != null && bones[j].boneWeight != null) { writer.Write((byte)4); writer.Write(skeleton.Lookup[bones[j].boneIndex[0]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[1]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[2]]); writer.Write(skeleton.Lookup[bones[j].boneIndex[3]]); writer.Write(bones[j].boneWeight[0]); writer.Write(bones[j].boneWeight[1]); writer.Write(bones[j].boneWeight[2]); writer.Write(bones[j].boneWeight[3]); } else { // bone -> size + index + weight writer.Write((byte)0); } } List <ModelIndiceModifiable> indexNew = new List <ModelIndiceModifiable>(); foreach (ModelIndice indice in index) { indexNew.Add(new ModelIndiceModifiable { v1 = indice.v1, v2 = indice.v2, v3 = indice.v3 }); } foreach (ModelIndiceModifiable indice in indexNew) { writer.Write((byte)3); writer.Write(indice.v1); writer.Write(indice.v2); writer.Write(indice.v3); } } } if (hardpoints != null) { // attachments foreach (PRHM.HardPoint hp in hardpoints.HardPoints) { writer.Write(IdToString("attachment_", GUID.Index(hp.HardPointGUID))); Matrix4 mat = hp.Matrix.ToOpenTK(); Vector3 pos = mat.ExtractTranslation(); Quaternion rot = mat.ExtractRotation(); writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); writer.Write(rot.W); } // extension 1.1 foreach (PRHM.HardPoint hp in hardpoints.HardPoints) { writer.Write(IdToString("bone", GUID.Index(hp.GUIDx012))); } } // ext 1.3: cloth writer.Write(0); // ext 1.4: embedded refpose if (skeleton != null) { for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { writer.Write(IdToString("bone", skeleton.IDs[i])); short parent = hierarchy[i]; // if (parent == -1) { // parent = (short)i; // } writer.Write(parent); Matrix3x4 bone = skeleton.Matrices34Inverted[i]; // Quaternion3D quat = new Quaternion3D(bone[0, 0], bone[0, 1], bone[0, 2], bone[0, 3]); // why are they different Quaternion3D quat = new Quaternion3D(bone[0, 3], bone[0, 0], bone[0, 1], bone[0, 2]); Vector3D rot = C3D.ToEulerAngles(quat); if (rot.X == -3.14159274f && rot.Y == 0 && rot.Z == 0) { rot = new Vector3D(0, 3.14159274f, 3.14159274f); // effectively the same but you know, eulers. } Vector3 scl = new Vector3(bone[1, 0], bone[1, 1], bone[1, 2]); Vector3 pos = new Vector3(bone[2, 0], bone[2, 1], bone[2, 2]); writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); writer.Write(scl.X); writer.Write(scl.Y); writer.Write(scl.Z); writer.Write(rot.X); writer.Write(rot.Y); writer.Write(rot.Z); } } } return(true); }
protected static double[] Rotations(double X, double Y, double Z, double I, double psi, double i, double omega, double lambda0, double beta0, C3D eclipticCoord) { double A6; double B6; double C6; //eclipticCoord = new CAA3DCoordinate(); double phi = psi - omega; //Rotation towards Jupiter's orbital plane double A1 = X; double B1 = Y * Math.Cos(I) - Z * Math.Sin(I); double C1 = Y * Math.Sin(I) + Z * Math.Cos(I); //Rotation towards the ascending node of the orbit of jupiter double A2 = A1 * Math.Cos(phi) - B1 * Math.Sin(phi); double B2 = A1 * Math.Sin(phi) + B1 * Math.Cos(phi); double C2 = C1; //Rotation towards the plane of the ecliptic double A3 = A2; double B3 = B2 * Math.Cos(i) - C2 * Math.Sin(i); double C3 = B2 * Math.Sin(i) + C2 * Math.Cos(i); //Rotation towards the vernal equinox double A4 = A3 * Math.Cos(omega) - B3 * Math.Sin(omega); double B4 = A3 * Math.Sin(omega) + B3 * Math.Cos(omega); double C4 = C3; const double JupiterRadiiToAU = 1.0 / 2095.0; // Not exact, but this is the value used elsewhere in the calculation eclipticCoord.X = A4 * JupiterRadiiToAU; eclipticCoord.Y = B4 * JupiterRadiiToAU; eclipticCoord.Z = C4 * JupiterRadiiToAU; double A5 = A4 * Math.Sin(lambda0) - B4 * Math.Cos(lambda0); double B5 = A4 * Math.Cos(lambda0) + B4 * Math.Sin(lambda0); double C5 = C4; A6 = A5; B6 = C5 * Math.Sin(beta0) + B5 * Math.Cos(beta0); C6 = C5 * Math.Cos(beta0) - B5 * Math.Sin(beta0); return(new double[] { A6, B6, C6 }); }
//////////////////////////////// Implementation /////////////////////////////// protected static GMDS CalculateHelper(double JD, double sunlongrad, double betarad, double R) { //What will be the return value GMDS details = new GMDS(); //Calculate the position of Jupiter decreased by the light travel time from Jupiter to the specified position double DELTA = 5; double PreviousLightTravelTime = 0; double LightTravelTime = ELL.DistanceToLightTime(DELTA); double x = 0; double y = 0; double z = 0; double l = 0; double lrad = 0; double b = 0; double brad = 0; double r = 0; double JD1 = JD - LightTravelTime; bool bIterate = true; while (bIterate) { //Calculate the position of Jupiter l = CAAJupiter.EclipticLongitude(JD1); lrad = CT.D2R(l); b = CAAJupiter.EclipticLatitude(JD1); brad = CT.D2R(b); r = CAAJupiter.RadiusVector(JD1); x = r * Math.Cos(brad) * Math.Cos(lrad) + R * Math.Cos(sunlongrad); y = r * Math.Cos(brad) * Math.Sin(lrad) + R * Math.Sin(sunlongrad); z = r * Math.Sin(brad) + R * Math.Sin(betarad); DELTA = Math.Sqrt(x * x + y * y + z * z); LightTravelTime = ELL.DistanceToLightTime(DELTA); //Prepare for the next loop around bIterate = (Math.Abs(LightTravelTime - PreviousLightTravelTime) > 2E-6); //2E-6 corresponds to 0.17 of a second if (bIterate) { JD1 = JD - LightTravelTime; PreviousLightTravelTime = LightTravelTime; } } //Calculate Jupiter's Longitude and Latitude double lambda0 = Math.Atan2(y, x); double beta0 = Math.Atan(z / Math.Sqrt(x * x + y * y)); double t = JD - 2443000.5 - LightTravelTime; //Calculate the mean longitudes double l1 = 106.07719 + 203.488955790 * t; double l1rad = CT.D2R(l1); double l2 = 175.73161 + 101.374724735 * t; double l2rad = CT.D2R(l2); double l3 = 120.55883 + 50.317609207 * t; double l3rad = CT.D2R(l3); double l4 = 84.44459 + 21.571071177 * t; double l4rad = CT.D2R(l4); //Calculate the perijoves double pi1 = CT.D2R(CT.M360(97.0881 + 0.16138586 * t)); double pi2 = CT.D2R(CT.M360(154.8663 + 0.04726307 * t)); double pi3 = CT.D2R(CT.M360(188.1840 + 0.00712734 * t)); double pi4 = CT.D2R(CT.M360(335.2868 + 0.00184000 * t)); //Calculate the nodes on the equatorial plane of jupiter double w1 = 312.3346 - 0.13279386 * t; double w1rad = CT.D2R(w1); double w2 = 100.4411 - 0.03263064 * t; double w2rad = CT.D2R(w2); double w3 = 119.1942 - 0.00717703 * t; double w3rad = CT.D2R(w3); double w4 = 322.6186 - 0.00175934 * t; double w4rad = CT.D2R(w4); //Calculate the Principal inequality in the longitude of Jupiter double GAMMA = 0.33033 * Math.Sin(CT.D2R(163.679 + 0.0010512 * t)) + 0.03439 * Math.Sin(CT.D2R(34.486 - 0.0161731 * t)); //Calculate the "phase of free libration" double philambda = CT.D2R(199.6766 + 0.17379190 * t); //Calculate the longitude of the node of the equator of Jupiter on the ecliptic double psi = CT.D2R(316.5182 - 0.00000208 * t); //Calculate the mean anomalies of Jupiter and Saturn double G = CT.D2R(30.23756 + 0.0830925701 * t + GAMMA); double Gdash = CT.D2R(31.97853 + 0.0334597339 * t); //Calculate the longitude of the perihelion of Jupiter double PI = CT.D2R(13.469942); //Calculate the periodic terms in the longitudes of the satellites double Sigma1 = 0.47259 * Math.Sin(2 * (l1rad - l2rad)) + -0.03478 * Math.Sin(pi3 - pi4) + 0.01081 * Math.Sin(l2rad - 2 * l3rad + pi3) + 0.00738 * Math.Sin(philambda) + 0.00713 * Math.Sin(l2rad - 2 * l3rad + pi2) + -0.00674 * Math.Sin(pi1 + pi3 - 2 * PI - 2 * G) + 0.00666 * Math.Sin(l2rad - 2 * l3rad + pi4) + 0.00445 * Math.Sin(l1rad - pi3) + -0.00354 * Math.Sin(l1rad - l2rad) + -0.00317 * Math.Sin(2 * psi - 2 * PI) + 0.00265 * Math.Sin(l1rad - pi4) + -0.00186 * Math.Sin(G) + 0.00162 * Math.Sin(pi2 - pi3) + 0.00158 * Math.Sin(4 * (l1rad - l2rad)) + -0.00155 * Math.Sin(l1rad - l3rad) + -0.00138 * Math.Sin(psi + w3rad - 2 * PI - 2 * G) + -0.00115 * Math.Sin(2 * (l1rad - 2 * l2rad + w2rad)) + 0.00089 * Math.Sin(pi2 - pi4) + 0.00085 * Math.Sin(l1rad + pi3 - 2 * PI - 2 * G) + 0.00083 * Math.Sin(w2rad - w3rad) + 0.00053 * Math.Sin(psi - w2rad); double Sigma2 = 1.06476 * Math.Sin(2 * (l2rad - l3rad)) + 0.04256 * Math.Sin(l1rad - 2 * l2rad + pi3) + 0.03581 * Math.Sin(l2rad - pi3) + 0.02395 * Math.Sin(l1rad - 2 * l2rad + pi4) + 0.01984 * Math.Sin(l2rad - pi4) + -0.01778 * Math.Sin(philambda) + 0.01654 * Math.Sin(l2rad - pi2) + 0.01334 * Math.Sin(l2rad - 2 * l3rad + pi2) + 0.01294 * Math.Sin(pi3 - pi4) + -0.01142 * Math.Sin(l2rad - l3rad) + -0.01057 * Math.Sin(G) + -0.00775 * Math.Sin(2 * (psi - PI)) + 0.00524 * Math.Sin(2 * (l1rad - l2rad)) + -0.00460 * Math.Sin(l1rad - l3rad) + 0.00316 * Math.Sin(psi - 2 * G + w3rad - 2 * PI) + -0.00203 * Math.Sin(pi1 + pi3 - 2 * PI - 2 * G) + 0.00146 * Math.Sin(psi - w3rad) + -0.00145 * Math.Sin(2 * G) + 0.00125 * Math.Sin(psi - w4rad) + -0.00115 * Math.Sin(l1rad - 2 * l3rad + pi3) + -0.00094 * Math.Sin(2 * (l2rad - w2rad)) + 0.00086 * Math.Sin(2 * (l1rad - 2 * l2rad + w2rad)) + -0.00086 * Math.Sin(5 * Gdash - 2 * G + CT.D2R(52.225)) + -0.00078 * Math.Sin(l2rad - l4rad) + -0.00064 * Math.Sin(3 * l3rad - 7 * l4rad + 4 * pi4) + 0.00064 * Math.Sin(pi1 - pi4) + -0.00063 * Math.Sin(l1rad - 2 * l3rad + pi4) + 0.00058 * Math.Sin(w3rad - w4rad) + 0.00056 * Math.Sin(2 * (psi - PI - G)) + 0.00056 * Math.Sin(2 * (l2rad - l4rad)) + 0.00055 * Math.Sin(2 * (l1rad - l3rad)) + 0.00052 * Math.Sin(3 * l3rad - 7 * l4rad + pi3 + 3 * pi4) + -0.00043 * Math.Sin(l1rad - pi3) + 0.00041 * Math.Sin(5 * (l2rad - l3rad)) + 0.00041 * Math.Sin(pi4 - PI) + 0.00032 * Math.Sin(w2rad - w3rad) + 0.00032 * Math.Sin(2 * (l3rad - G - PI)); double Sigma3 = 0.16490 * Math.Sin(l3rad - pi3) + 0.09081 * Math.Sin(l3rad - pi4) + -0.06907 * Math.Sin(l2rad - l3rad) + 0.03784 * Math.Sin(pi3 - pi4) + 0.01846 * Math.Sin(2 * (l3rad - l4rad)) + -0.01340 * Math.Sin(G) + -0.01014 * Math.Sin(2 * (psi - PI)) + 0.00704 * Math.Sin(l2rad - 2 * l3rad + pi3) + -0.00620 * Math.Sin(l2rad - 2 * l3rad + pi2) + -0.00541 * Math.Sin(l3rad - l4rad) + 0.00381 * Math.Sin(l2rad - 2 * l3rad + pi4) + 0.00235 * Math.Sin(psi - w3rad) + 0.00198 * Math.Sin(psi - w4rad) + 0.00176 * Math.Sin(philambda) + 0.00130 * Math.Sin(3 * (l3rad - l4rad)) + 0.00125 * Math.Sin(l1rad - l3rad) + -0.00119 * Math.Sin(5 * Gdash - 2 * G + CT.D2R(52.225)) + 0.00109 * Math.Sin(l1rad - l2rad) + -0.00100 * Math.Sin(3 * l3rad - 7 * l4rad + 4 * pi4) + 0.00091 * Math.Sin(w3rad - w4rad) + 0.00080 * Math.Sin(3 * l3rad - 7 * l4rad + pi3 + 3 * pi4) + -0.00075 * Math.Sin(2 * l2rad - 3 * l3rad + pi3) + 0.00072 * Math.Sin(pi1 + pi3 - 2 * PI - 2 * G) + 0.00069 * Math.Sin(pi4 - PI) + -0.00058 * Math.Sin(2 * l3rad - 3 * l4rad + pi4) + -0.00057 * Math.Sin(l3rad - 2 * l4rad + pi4) + 0.00056 * Math.Sin(l3rad + pi3 - 2 * PI - 2 * G) + -0.00052 * Math.Sin(l2rad - 2 * l3rad + pi1) + -0.00050 * Math.Sin(pi2 - pi3) + 0.00048 * Math.Sin(l3rad - 2 * l4rad + pi3) + -0.00045 * Math.Sin(2 * l2rad - 3 * l3rad + pi4) + -0.00041 * Math.Sin(pi2 - pi4) + -0.00038 * Math.Sin(2 * G) + -0.00037 * Math.Sin(pi3 - pi4 + w3rad - w4rad) + -0.00032 * Math.Sin(3 * l3rad - 7 * l4rad + 2 * pi3 + 2 * pi4) + 0.00030 * Math.Sin(4 * (l3rad - l4rad)) + 0.00029 * Math.Sin(l3rad + pi4 - 2 * PI - 2 * G) + -0.00028 * Math.Sin(w3rad + psi - 2 * PI - 2 * G) + 0.00026 * Math.Sin(l3rad - PI - G) + 0.00024 * Math.Sin(l2rad - 3 * l3rad + 2 * l4rad) + 0.00021 * Math.Sin(l3rad - PI - G) + -0.00021 * Math.Sin(l3rad - pi2) + 0.00017 * Math.Sin(2 * (l3rad - pi3)); double Sigma4 = 0.84287 * Math.Sin(l4rad - pi4) + 0.03431 * Math.Sin(pi4 - pi3) + -0.03305 * Math.Sin(2 * (psi - PI)) + -0.03211 * Math.Sin(G) + -0.01862 * Math.Sin(l4rad - pi3) + 0.01186 * Math.Sin(psi - w4rad) + 0.00623 * Math.Sin(l4rad + pi4 - 2 * G - 2 * PI) + 0.00387 * Math.Sin(2 * (l4rad - pi4)) + -0.00284 * Math.Sin(5 * Gdash - 2 * G + CT.D2R(52.225)) + -0.00234 * Math.Sin(2 * (psi - pi4)) + -0.00223 * Math.Sin(l3rad - l4rad) + -0.00208 * Math.Sin(l4rad - PI) + 0.00178 * Math.Sin(psi + w4rad - 2 * pi4) + 0.00134 * Math.Sin(pi4 - PI) + 0.00125 * Math.Sin(2 * (l4rad - G - PI)) + -0.00117 * Math.Sin(2 * G) + -0.00112 * Math.Sin(2 * (l3rad - l4rad)) + 0.00107 * Math.Sin(3 * l3rad - 7 * l4rad + 4 * pi4) + 0.00102 * Math.Sin(l4rad - G - PI) + 0.00096 * Math.Sin(2 * l4rad - psi - w4rad) + 0.00087 * Math.Sin(2 * (psi - w4rad)) + -0.00085 * Math.Sin(3 * l3rad - 7 * l4rad + pi3 + 3 * pi4) + 0.00085 * Math.Sin(l3rad - 2 * l4rad + pi4) + -0.00081 * Math.Sin(2 * (l4rad - psi)) + 0.00071 * Math.Sin(l4rad + pi4 - 2 * PI - 3 * G) + 0.00061 * Math.Sin(l1rad - l4rad) + -0.00056 * Math.Sin(psi - w3rad) + -0.00054 * Math.Sin(l3rad - 2 * l4rad + pi3) + 0.00051 * Math.Sin(l2rad - l4rad) + 0.00042 * Math.Sin(2 * (psi - G - PI)) + 0.00039 * Math.Sin(2 * (pi4 - w4rad)) + 0.00036 * Math.Sin(psi + PI - pi4 - w4rad) + 0.00035 * Math.Sin(2 * Gdash - G + CT.D2R(188.37)) + -0.00035 * Math.Sin(l4rad - pi4 + 2 * PI - 2 * psi) + -0.00032 * Math.Sin(l4rad + pi4 - 2 * PI - G) + 0.00030 * Math.Sin(2 * Gdash - 2 * G + CT.D2R(149.15)) + 0.00029 * Math.Sin(3 * l3rad - 7 * l4rad + 2 * pi3 + 2 * pi4) + 0.00028 * Math.Sin(l4rad - pi4 + 2 * psi - 2 * PI) + -0.00028 * Math.Sin(2 * (l4rad - w4rad)) + -0.00027 * Math.Sin(pi3 - pi4 + w3rad - w4rad) + -0.00026 * Math.Sin(5 * Gdash - 3 * G + CT.D2R(188.37)) + 0.00025 * Math.Sin(w4rad - w3rad) + -0.00025 * Math.Sin(l2rad - 3 * l3rad + 2 * l4rad) + -0.00023 * Math.Sin(3 * (l3rad - l4rad)) + 0.00021 * Math.Sin(2 * l4rad - 2 * PI - 3 * G) + -0.00021 * Math.Sin(2 * l3rad - 3 * l4rad + pi4) + 0.00019 * Math.Sin(l4rad - pi4 - G) + -0.00019 * Math.Sin(2 * l4rad - pi3 - pi4) + -0.00018 * Math.Sin(l4rad - pi4 + G) + -0.00016 * Math.Sin(l4rad + pi3 - 2 * PI - 2 * G); details.Satellite1.MeanLongitude = CT.M360(l1); details.Satellite1.TrueLongitude = CT.M360(l1 + Sigma1); double L1 = CT.D2R(details.Satellite1.TrueLongitude); details.Satellite2.MeanLongitude = CT.M360(l2); details.Satellite2.TrueLongitude = CT.M360(l2 + Sigma2); double L2 = CT.D2R(details.Satellite2.TrueLongitude); details.Satellite3.MeanLongitude = CT.M360(l3); details.Satellite3.TrueLongitude = CT.M360(l3 + Sigma3); double L3 = CT.D2R(details.Satellite3.TrueLongitude); details.Satellite4.MeanLongitude = CT.M360(l4); details.Satellite4.TrueLongitude = CT.M360(l4 + Sigma4); double L4 = CT.D2R(details.Satellite4.TrueLongitude); //Calculate the periodic terms in the latitudes of the satellites double B1 = Math.Atan(0.0006393 * Math.Sin(L1 - w1rad) + 0.0001825 * Math.Sin(L1 - w2rad) + 0.0000329 * Math.Sin(L1 - w3rad) + -0.0000311 * Math.Sin(L1 - psi) + 0.0000093 * Math.Sin(L1 - w4rad) + 0.0000075 * Math.Sin(3 * L1 - 4 * l2rad - 1.9927 * Sigma1 + w2rad) + 0.0000046 * Math.Sin(L1 + psi - 2 * PI - 2 * G)); details.Satellite1.EquatorialLatitude = CT.R2D(B1); double B2 = Math.Atan(0.0081004 * Math.Sin(L2 - w2rad) + 0.0004512 * Math.Sin(L2 - w3rad) + -0.0003284 * Math.Sin(L2 - psi) + 0.0001160 * Math.Sin(L2 - w4rad) + 0.0000272 * Math.Sin(l1rad - 2 * l3rad + 1.0146 * Sigma2 + w2rad) + -0.0000144 * Math.Sin(L2 - w1rad) + 0.0000143 * Math.Sin(L2 + psi - 2 * PI - 2 * G) + 0.0000035 * Math.Sin(L2 - psi + G) + -0.0000028 * Math.Sin(l1rad - 2 * l3rad + 1.0146 * Sigma2 + w3rad)); details.Satellite2.EquatorialLatitude = CT.R2D(B2); double B3 = Math.Atan(0.0032402 * Math.Sin(L3 - w3rad) + -0.0016911 * Math.Sin(L3 - psi) + 0.0006847 * Math.Sin(L3 - w4rad) + -0.0002797 * Math.Sin(L3 - w2rad) + 0.0000321 * Math.Sin(L3 + psi - 2 * PI - 2 * G) + 0.0000051 * Math.Sin(L3 - psi + G) + -0.0000045 * Math.Sin(L3 - psi - G) + -0.0000045 * Math.Sin(L3 + psi - 2 * PI) + 0.0000037 * Math.Sin(L3 + psi - 2 * PI - 3 * G) + 0.0000030 * Math.Sin(2 * l2rad - 3 * L3 + 4.03 * Sigma3 + w2rad) + -0.0000021 * Math.Sin(2 * l2rad - 3 * L3 + 4.03 * Sigma3 + w3rad)); details.Satellite3.EquatorialLatitude = CT.R2D(B3); double B4 = Math.Atan(-0.0076579 * Math.Sin(L4 - psi) + 0.0044134 * Math.Sin(L4 - w4rad) + -0.0005112 * Math.Sin(L4 - w3rad) + 0.0000773 * Math.Sin(L4 + psi - 2 * PI - 2 * G) + 0.0000104 * Math.Sin(L4 - psi + G) + -0.0000102 * Math.Sin(L4 - psi - G) + 0.0000088 * Math.Sin(L4 + psi - 2 * PI - 3 * G) + -0.0000038 * Math.Sin(L4 + psi - 2 * PI - G)); details.Satellite4.EquatorialLatitude = CT.R2D(B4); //Calculate the periodic terms for the radius vector details.Satellite1.r = 5.90569 * (1 + (-0.0041339 * Math.Cos(2 * (l1rad - l2rad)) + -0.0000387 * Math.Cos(l1rad - pi3) + -0.0000214 * Math.Cos(l1rad - pi4) + 0.0000170 * Math.Cos(l1rad - l2rad) + -0.0000131 * Math.Cos(4 * (l1rad - l2rad)) + 0.0000106 * Math.Cos(l1rad - l3rad) + -0.0000066 * Math.Cos(l1rad + pi3 - 2 * PI - 2 * G))); details.Satellite2.r = 9.39657 * (1 + (0.0093848 * Math.Cos(l1rad - l2rad) + -0.0003116 * Math.Cos(l2rad - pi3) + -0.0001744 * Math.Cos(l2rad - pi4) + -0.0001442 * Math.Cos(l2rad - pi2) + 0.0000553 * Math.Cos(l2rad - l3rad) + 0.0000523 * Math.Cos(l1rad - l3rad) + -0.0000290 * Math.Cos(2 * (l1rad - l2rad)) + 0.0000164 * Math.Cos(2 * (l2rad - w2rad)) + 0.0000107 * Math.Cos(l1rad - 2 * l3rad + pi3) + -0.0000102 * Math.Cos(l2rad - pi1) + -0.0000091 * Math.Cos(2 * (l1rad - l3rad)))); details.Satellite3.r = 14.98832 * (1 + (-0.0014388 * Math.Cos(l3rad - pi3) + -0.0007919 * Math.Cos(l3rad - pi4) + 0.0006342 * Math.Cos(l2rad - l3rad) + -0.0001761 * Math.Cos(2 * (l3rad - l4rad)) + 0.0000294 * Math.Cos(l3rad - l4rad) + -0.0000156 * Math.Cos(3 * (l3rad - l4rad)) + 0.0000156 * Math.Cos(l1rad - l3rad) + -0.0000153 * Math.Cos(l1rad - l2rad) + 0.0000070 * Math.Cos(2 * l2rad - 3 * l3rad + pi3) + -0.0000051 * Math.Cos(l3rad + pi3 - 2 * PI - 2 * G))); details.Satellite4.r = 26.36273 * (1 + (-0.0073546 * Math.Cos(l4rad - pi4) + 0.0001621 * Math.Cos(l4rad - pi3) + 0.0000974 * Math.Cos(l3rad - l4rad) + -0.0000543 * Math.Cos(l4rad + pi4 - 2 * PI - 2 * G) + -0.0000271 * Math.Cos(2 * (l4rad - pi4)) + 0.0000182 * Math.Cos(l4rad - PI) + 0.0000177 * Math.Cos(2 * (l3rad - l4rad)) + -0.0000167 * Math.Cos(2 * l4rad - psi - w4rad) + 0.0000167 * Math.Cos(psi - w4rad) + -0.0000155 * Math.Cos(2 * (l4rad - PI - G)) + 0.0000142 * Math.Cos(2 * (l4rad - psi)) + 0.0000105 * Math.Cos(l1rad - l4rad) + 0.0000092 * Math.Cos(l2rad - l4rad) + -0.0000089 * Math.Cos(l4rad - PI - G) + -0.0000062 * Math.Cos(l4rad + pi4 - 2 * PI - 3 * G) + 0.0000048 * Math.Cos(2 * (l4rad - w4rad)))); //Calculate T0 double T0 = (JD - 2433282.423) / 36525; //Calculate the precession in longitude from Epoch B1950 to the date double P = CT.D2R(1.3966626 * T0 + 0.0003088 * T0 * T0); //Add it to L1 - L4 and psi L1 += P; details.Satellite1.TropicalLongitude = CT.M360(CT.R2D(L1)); L2 += P; details.Satellite2.TropicalLongitude = CT.M360(CT.R2D(L2)); L3 += P; details.Satellite3.TropicalLongitude = CT.M360(CT.R2D(L3)); L4 += P; details.Satellite4.TropicalLongitude = CT.M360(CT.R2D(L4)); psi += P; //Calculate the inclination of Jupiter's axis of rotation on the orbital plane double T = (JD - 2415020.5) / 36525; double I = 3.120262 + 0.0006 * T; double Irad = CT.D2R(I); double X1 = details.Satellite1.r * Math.Cos(L1 - psi) * Math.Cos(B1); double X2 = details.Satellite2.r * Math.Cos(L2 - psi) * Math.Cos(B2); double X3 = details.Satellite3.r * Math.Cos(L3 - psi) * Math.Cos(B3); double X4 = details.Satellite4.r * Math.Cos(L4 - psi) * Math.Cos(B4); double X5 = 0; double Y1 = details.Satellite1.r * Math.Sin(L1 - psi) * Math.Cos(B1); double Y2 = details.Satellite2.r * Math.Sin(L2 - psi) * Math.Cos(B2); double Y3 = details.Satellite3.r * Math.Sin(L3 - psi) * Math.Cos(B3); double Y4 = details.Satellite4.r * Math.Sin(L4 - psi) * Math.Cos(B4); double Y5 = 0; double Z1 = details.Satellite1.r * Math.Sin(B1); double Z2 = details.Satellite2.r * Math.Sin(B2); double Z3 = details.Satellite3.r * Math.Sin(B3); double Z4 = details.Satellite4.r * Math.Sin(B4); double Z5 = 1; //Now do the rotations, first for the ficticious 5th satellite, so that we can calculate D double omega = CT.D2R(EPO.JupiterLongitudeAscendingNode(JD)); double i = CT.D2R(EPO.JupiterInclination(JD)); double A6 = 0; double B6 = 0; double C6 = 0; C3D north = new C3D(); double[] abc = Rotations(X5, Y5, Z5, Irad, psi, i, omega, lambda0, beta0, north); A6 = abc[0]; B6 = abc[1]; C6 = abc[2]; double D = Math.Atan2(A6, C6); //Now calculate the values for satellite 1 abc = Rotations(X1, Y1, Z1, Irad, psi, i, omega, lambda0, beta0, details.Satellite1.EclipticRectangularCoordinates); A6 = abc[0]; B6 = abc[1]; C6 = abc[2]; details.Satellite1.TrueRectangularCoordinates.X = A6 * Math.Cos(D) - C6 * Math.Sin(D); details.Satellite1.TrueRectangularCoordinates.Y = A6 * Math.Sin(D) + C6 * Math.Cos(D); details.Satellite1.TrueRectangularCoordinates.Z = B6; //Now calculate the values for satellite 2 abc = Rotations(X2, Y2, Z2, Irad, psi, i, omega, lambda0, beta0, details.Satellite2.EclipticRectangularCoordinates); A6 = abc[0]; B6 = abc[1]; C6 = abc[2]; details.Satellite2.TrueRectangularCoordinates.X = A6 * Math.Cos(D) - C6 * Math.Sin(D); details.Satellite2.TrueRectangularCoordinates.Y = A6 * Math.Sin(D) + C6 * Math.Cos(D); details.Satellite2.TrueRectangularCoordinates.Z = B6; //Now calculate the values for satellite 3 abc = Rotations(X3, Y3, Z3, Irad, psi, i, omega, lambda0, beta0, details.Satellite3.EclipticRectangularCoordinates); A6 = abc[0]; B6 = abc[1]; C6 = abc[2]; details.Satellite3.TrueRectangularCoordinates.X = A6 * Math.Cos(D) - C6 * Math.Sin(D); details.Satellite3.TrueRectangularCoordinates.Y = A6 * Math.Sin(D) + C6 * Math.Cos(D); details.Satellite3.TrueRectangularCoordinates.Z = B6; //And finally for satellite 4 abc = Rotations(X4, Y4, Z4, Irad, psi, i, omega, lambda0, beta0, details.Satellite4.EclipticRectangularCoordinates); A6 = abc[0]; B6 = abc[1]; C6 = abc[2]; details.Satellite4.TrueRectangularCoordinates.X = A6 * Math.Cos(D) - C6 * Math.Sin(D); details.Satellite4.TrueRectangularCoordinates.Y = A6 * Math.Sin(D) + C6 * Math.Cos(D); details.Satellite4.TrueRectangularCoordinates.Z = B6; //apply the differential light-time correction details.Satellite1.ApparentRectangularCoordinates.X = details.Satellite1.TrueRectangularCoordinates.X + Math.Abs(details.Satellite1.TrueRectangularCoordinates.Z) / 17295 * Math.Sqrt(1 - (details.Satellite1.TrueRectangularCoordinates.X / details.Satellite1.r) * (details.Satellite1.TrueRectangularCoordinates.X / details.Satellite1.r)); details.Satellite1.ApparentRectangularCoordinates.Y = details.Satellite1.TrueRectangularCoordinates.Y; details.Satellite1.ApparentRectangularCoordinates.Z = details.Satellite1.TrueRectangularCoordinates.Z; details.Satellite2.ApparentRectangularCoordinates.X = details.Satellite2.TrueRectangularCoordinates.X + Math.Abs(details.Satellite2.TrueRectangularCoordinates.Z) / 21819 * Math.Sqrt(1 - (details.Satellite2.TrueRectangularCoordinates.X / details.Satellite2.r) * (details.Satellite2.TrueRectangularCoordinates.X / details.Satellite2.r)); details.Satellite2.ApparentRectangularCoordinates.Y = details.Satellite2.TrueRectangularCoordinates.Y; details.Satellite2.ApparentRectangularCoordinates.Z = details.Satellite2.TrueRectangularCoordinates.Z; details.Satellite3.ApparentRectangularCoordinates.X = details.Satellite3.TrueRectangularCoordinates.X + Math.Abs(details.Satellite3.TrueRectangularCoordinates.Z) / 27558 * Math.Sqrt(1 - (details.Satellite3.TrueRectangularCoordinates.X / details.Satellite3.r) * (details.Satellite3.TrueRectangularCoordinates.X / details.Satellite3.r)); details.Satellite3.ApparentRectangularCoordinates.Y = details.Satellite3.TrueRectangularCoordinates.Y; details.Satellite3.ApparentRectangularCoordinates.Z = details.Satellite3.TrueRectangularCoordinates.Z; details.Satellite4.ApparentRectangularCoordinates.X = details.Satellite4.TrueRectangularCoordinates.X + Math.Abs(details.Satellite4.TrueRectangularCoordinates.Z) / 36548 * Math.Sqrt(1 - (details.Satellite4.TrueRectangularCoordinates.X / details.Satellite4.r) * (details.Satellite4.TrueRectangularCoordinates.X / details.Satellite4.r)); details.Satellite4.ApparentRectangularCoordinates.Y = details.Satellite4.TrueRectangularCoordinates.Y; details.Satellite4.ApparentRectangularCoordinates.Z = details.Satellite4.TrueRectangularCoordinates.Z; //apply the perspective effect correction double W = DELTA / (DELTA + details.Satellite1.TrueRectangularCoordinates.Z / 2095); details.Satellite1.ApparentRectangularCoordinates.X *= W; details.Satellite1.ApparentRectangularCoordinates.Y *= W; W = DELTA / (DELTA + details.Satellite2.TrueRectangularCoordinates.Z / 2095); details.Satellite2.ApparentRectangularCoordinates.X *= W; details.Satellite2.ApparentRectangularCoordinates.Y *= W; W = DELTA / (DELTA + details.Satellite3.TrueRectangularCoordinates.Z / 2095); details.Satellite3.ApparentRectangularCoordinates.X *= W; details.Satellite3.ApparentRectangularCoordinates.Y *= W; W = DELTA / (DELTA + details.Satellite4.TrueRectangularCoordinates.Z / 2095); details.Satellite4.ApparentRectangularCoordinates.X *= W; details.Satellite4.ApparentRectangularCoordinates.Y *= W; return(details); }
public bool Write(Chunked model, Stream output, bool keepOpen = false) { culture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = culture; IChunk chunk = model.FindNextChunk("lksm").Value; if (chunk == null) { return(false); } lksm skeleton = (lksm)chunk; short[] hierarchy = (short[])skeleton.Hierarchy.Clone(); HashSet <short> weightedParNodes = new HashSet <short>(); Dictionary <int, HTLC.ClothNode> nodeMap = new Dictionary <int, HTLC.ClothNode>(); HTLC cloth = model.FindNextChunk("HTLC").Value as HTLC; if (cloth != null) { uint clothIndex = 0; foreach (HTLC.ClothNode[] nodeCollection in cloth.Nodes) { if (nodeCollection == null) { continue; } int nodeIndex = 0; foreach (HTLC.ClothNode node in nodeCollection) { int parentRaw = node.VerticalParent; if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex) && cloth.NodeBones[clothIndex].ContainsKey(parentRaw)) { // good code: if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = cloth.NodeBones[clothIndex][parentRaw]; if (cloth.NodeBones[clothIndex][parentRaw] == -1) { HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; weightedParNodes.Add(cloth.NodeBones[clothIndex][nodeIndex]); } } // else: on subskele // todo: add subskelebones? } else { if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) // if on main skele // good code: { if (cloth.NodeBones[clothIndex][nodeIndex] != -1) { hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = -1; HTLC.ClothNodeWeight weightedBone = node.Bones.Aggregate((i1, i2) => i1.Weight > i2.Weight ? i1 : i2); hierarchy[cloth.NodeBones[clothIndex][nodeIndex]] = weightedBone.Bone; weightedParNodes.Add(cloth.NodeBones[clothIndex][nodeIndex]); } // else: on subskele // todo: add subskelebones? } } if (cloth.NodeBones[clothIndex].ContainsKey(nodeIndex)) { // good code: nodeMap[cloth.NodeBones[clothIndex][nodeIndex]] = node; } nodeIndex++; } clothIndex++; } } using (StreamWriter writer = new StreamWriter(output, Encoding.Default, 512, keepOpen)) { writer.WriteLine("{0}", skeleton.Data.bonesAbs); writer.WriteLine("version 1"); writer.WriteLine("nodes"); for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { writer.WriteLine("{0} \"bone_{1:X4}\" {2}", i, skeleton.IDs[i], hierarchy[i]); } writer.WriteLine("end"); writer.WriteLine("skeleton"); writer.WriteLine("time 0"); for (int i = 0; i < skeleton.Data.bonesAbs; ++i) { Matrix3x4 bone = skeleton.Matrices34Inverted[i]; Quaternion3D quat = new Quaternion3D(bone[0, 3], bone[0, 0], bone[0, 1], bone[0, 2]); Vector3D rot = C3D.ToEulerAngles(quat); Vector3 scale = new Vector3(bone[1, 0], bone[1, 1], bone[1, 2]); Vector3 pos = new Vector3(bone[2, 0], bone[2, 1], bone[2, 2]); if (nodeMap.ContainsKey(i)) { HTLC.ClothNode thisNode = nodeMap[i]; if (weightedParNodes.Contains((short)i)) { Vector3 pos2 = GetGlobalPos(skeleton.Matrices34Inverted, hierarchy[i], hierarchy); pos.X = thisNode.X - pos2.X; pos.Y = thisNode.Y - pos2.Y; pos.Z = thisNode.Z - pos2.Z; } else if (nodeMap.ContainsKey(hierarchy[i])) { HTLC.ClothNode parentNode = nodeMap[hierarchy[i]]; pos.X = thisNode.X - parentNode.X; pos.Y = thisNode.Y - parentNode.Y; pos.Z = thisNode.Z - parentNode.Z; } else { pos.X = thisNode.X; pos.Y = thisNode.Y; pos.Z = thisNode.Z; } } if (rot.X == -3.14159274f && rot.Y == 0 && rot.Z == 0) { rot = new Vector3D(0, 3.14159274f, 3.14159274f); // effectively the same but you know, eulers. } writer.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} {1:0.000000} {2:0.000000} {3:0.000000} {4:0.000000} {5:0.000000} {6:0.000000} {7:0.000000} {8:0.000000} {9:0.000000}", i, pos.X, pos.Y, pos.Z, rot.X, rot.Y, rot.Z, scale.X, scale.Y, scale.Z)); } } return(true); }