static Layer parselayer(Queue <string> lines) { Layer thisLayer = new Layer(); while ((!(lines.Peek().Contains("$$LAYER") || lines.Peek().Contains("$$GEOMETRYEND"))) && (!lines.Peek().Equals(""))) //don't want to take more than we need. { GeomMetaData gmd = new GeomMetaData(); string line = lines.Dequeue(); gmd.power = Convert.ToDouble(line.Substring("$$POWER/".Length)); line = lines.Dequeue(); gmd.speed = Convert.ToDouble(line.Substring("$$SPEED/".Length)); line = lines.Dequeue(); gmd.focus = Convert.ToDouble(line.Substring("$$FOCUS/".Length)); line = lines.Dequeue(); GeomData tmp; if (line.Contains("$$POLYLINE")) { tmp = parsepolyline(line); } else if (line.Contains("$$HATCHES")) { tmp = parsehatches(line); } else { tmp = new GeomData(); //Error case? } tmp.MetaData = gmd; thisLayer.operations.Add(tmp); } return(thisLayer); }
static float GetYAnchorForHeight(float textHeight, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int heightAnchor = (int)data.anchor / 3; float lineHeight = (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; switch (heightAnchor) { case 0: return(-lineHeight); case 1: { float y = -textHeight / 2.0f - lineHeight; if (_fontInst.version >= 2) { float ty = _fontInst.texelSize.y * data.scale.y; return(Mathf.Floor(y / ty) * ty); } else { return(y); } } case 2: return(-textHeight - lineHeight); } return(-lineHeight); }
static float GetXAnchorForWidth(float lineWidth, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int widthAnchor = (int)data.anchor % 3; switch (widthAnchor) { case 0: return(0.0f); // left case 1: // center { float x = -lineWidth / 2.0f; if (_fontInst.version >= 2) { float tx = _fontInst.texelSize.x * data.scale.x; return(Mathf.Floor(x / tx) * tx); } return(x); } case 2: return(-lineWidth); // right } return(0.0f); }
public static void GetTextMeshGeomDesc(out int numVertices, out int numIndices, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; numVertices = data.maxChars * 4; numIndices = data.maxChars * 6; }
static void Main(string[] args) { byte[] buffer = File.ReadAllBytes("./test.geomtuple.dimbin"); GeomData geom = GeomTuple.Parse(buffer); Console.WriteLine(geom); AttributeData attr; geom.attributes.TryGetValue("position", out attr); Console.WriteLine(attr); Console.WriteLine(geom.index); }
protected override void OnShapeSetMaterialProperty(Shape shape) { GeomData geomData = GetGeomDataByShape(shape); if (geomData != null) { dGeomID geomID = (geomData.transformID != dGeomID.Zero) ? geomData.transformID : geomData.geomID; Ode.SetShapeMaterialProperties(geomID, shape.Hardness, shape.Restitution, shape.DynamicFriction, shape.StaticFriction); } }
public static void SetTextMeshIndices(this GeomData geomData, int[] indices, int offset, int vStart) { for (int i = 0; i < geomData.CurrentAllocatedCharacters; ++i) { indices[offset + i * 6 + 0] = vStart + i * 4 + 0; indices[offset + i * 6 + 1] = vStart + i * 4 + 1; indices[offset + i * 6 + 2] = vStart + i * 4 + 3; indices[offset + i * 6 + 3] = vStart + i * 4 + 2; indices[offset + i * 6 + 4] = vStart + i * 4 + 0; indices[offset + i * 6 + 5] = vStart + i * 4 + 3; } }
protected override void OnShapeSetContactGroup(Shape shape) { base.OnShapeSetContactGroup(shape); GeomData geomData = GetGeomDataByShape(shape); if (geomData != null) { dGeomID geomID = (geomData.transformID != dGeomID.Zero) ? geomData.transformID : geomData.geomID; Ode.SetShapeContractGroup(geomID, shape.ContactGroup); } }
public static void SetTextMeshIndices(int[] indices, int offset, int vStart, GeomData geomData, int target) { tk2dTextMeshData data = geomData.textMeshData; for (int i = 0; i < data.maxChars; ++i) { indices[offset + i * 6 + 0] = vStart + i * 4 + 0; indices[offset + i * 6 + 1] = vStart + i * 4 + 1; indices[offset + i * 6 + 2] = vStart + i * 4 + 3; indices[offset + i * 6 + 3] = vStart + i * 4 + 2; indices[offset + i * 6 + 4] = vStart + i * 4 + 0; indices[offset + i * 6 + 5] = vStart + i * 4 + 3; } }
void CalculateBodyMass() { float totalVolume = 0; if (MassMethod == MassMethods.Manually) { for (int nShape = 0; nShape < Shapes.Length; nShape++) { totalVolume += Shapes[nShape].Volume; } if (totalVolume == 0) { totalVolume = .001f; } } Ode.dMass bodyMass = new Ode.dMass(); bool bodyMassInitialized = false; for (int nShape = 0; nShape < Shapes.Length; nShape++) { Shape shape = Shapes[nShape]; Ode.dMass shapeMass = new Ode.dMass(); float shapeDensity; if (MassMethod == MassMethods.Manually) { shapeDensity = Mass / totalVolume; } else { shapeDensity = shape.Density; } if (shapeDensity <= 0) { shapeDensity = .0001f; } switch (shape.ShapeType) { case Shape.Type.Box: { BoxShape boxShape = (BoxShape)shape; Ode.dMassSetBox(ref shapeMass, shapeDensity, boxShape.Dimensions.X, boxShape.Dimensions.Y, boxShape.Dimensions.Z); } break; case Shape.Type.Sphere: { SphereShape sphereShape = (SphereShape)shape; Ode.dMassSetSphere(ref shapeMass, shapeDensity, sphereShape.Radius); } break; case Shape.Type.Capsule: { CapsuleShape capsuleShape = (CapsuleShape)shape; Ode.dMassSetCapsule(ref shapeMass, shapeDensity, 3, capsuleShape.Radius, capsuleShape.Length); } break; case Shape.Type.Cylinder: { CylinderShape cylinderShape = (CylinderShape)shape; Ode.dMassSetCylinder(ref shapeMass, shapeDensity, 3, cylinderShape.Radius, cylinderShape.Length); } break; case Shape.Type.Mesh: { GeomData geomData = geomDatas[nShape]; //ignore this shape if (geomData == null) { continue; } IntPtr geomID; if (geomData.transformID == dGeomID.Zero) { geomID = geomData.geomID; } else { geomID = geomData.transformID; } //ignore this shape if (geomID == dGeomID.Zero) { continue; } Ode.Aabb aabb = new Ode.Aabb(); Ode.dGeomGetAABB(geomID, ref aabb); Ode.dMassSetBox(ref shapeMass, shapeDensity, aabb.maxx - aabb.minx, aabb.maxy - aabb.miny, aabb.maxz - aabb.minz); //correct shapeMass.mass = shape.Volume * shapeDensity; if (shapeMass.mass <= 0) { shapeMass.mass = .001f; } } break; default: Trace.Assert(false); break; } if (shape.Rotation != Quat.Identity) { Mat3 mat3; shape.Rotation.ToMat3(out mat3); Ode.dMatrix3 odeMat3; Convert.ToODE(ref mat3, out odeMat3); Ode.dMassRotate(ref shapeMass, ref odeMat3); } if (shape.Position != Vec3.Zero) { Ode.dMassTranslate(ref shapeMass, shape.Position.X, shape.Position.Y, shape.Position.Z); } if (!bodyMassInitialized) { bodyMass = shapeMass; bodyMassInitialized = true; } else { Ode.dMassAdd(ref bodyMass, ref shapeMass); } } if (MassMethod == MassMethods.Manually) { bodyMass.mass = Mass; if (bodyMass.mass <= 0) { bodyMass.mass = .0001f; } } if (bodyMass.mass != 0) { //if( CenterOfMassAuto ) // Log.Warning( "ODEBody: CenterOfMassAuto is not supported on ODE physics." ); //!!!!!!тут вручную введенное положение цента масс Ode.dMassTranslate(ref bodyMass, -bodyMass.c.X, -bodyMass.c.Y, -bodyMass.c.Z); Ode.dBodySetMass(bodyID, ref bodyMass); } ////calculate mNonSymmetricInertia //nonSymmetricInertia = // !AreEqual( bodyMass.I.M00, bodyMass.I.M11 ) || // !AreEqual( bodyMass.I.M11, bodyMass.I.M22 ); }
public static float GetYAnchorForHeight(float textHeight, GeomData geomData) { tk2dTextMeshData textMeshData = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; int num = (int) (textMeshData.anchor / TextAnchor.MiddleLeft); float num2 = (fontInst.lineHeight + textMeshData.lineSpacing) * textMeshData.scale.y; switch (num) { case 0: return -num2; case 1: { float num3 = (-textHeight / 2f) - num2; if (fontInst.version < 2) { return num3; } float num4 = fontInst.texelSize.y * textMeshData.scale.y; return (Mathf.Floor(num3 / num4) * num4); } case 2: return (-textHeight - num2); } return -num2; }
/// <summary> /// Calculates the mesh dimensions for the given string /// and returns a width and height. /// </summary> public static Vector2 GetMeshDimensionsForString(string str, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; float maxWidth = 0.0f; float cursorX = 0.0f; float cursorY = 0.0f; bool ignoreNextCharacter = false; int target = 0; for (int i = 0; i < str.Length && target < data.maxChars; ++i) { if (ignoreNextCharacter) { ignoreNextCharacter = false; continue; } int idx = str[i]; if (idx == '\n') { maxWidth = Mathf.Max(cursorX, maxWidth); cursorX = 0.0f; cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^' && i + 1 < str.Length) { if (str[i + 1] == '^') { ignoreNextCharacter = true; } else { int cmdLength = 0; switch (str[i + 1]) { case 'c': cmdLength = 5; break; case 'C': cmdLength = 9; break; case 'g': cmdLength = 9; break; case 'G': cmdLength = 17; break; } i += cmdLength; continue; } } } bool inlineHatChar = (idx == '^'); // Get the character from dictionary / array tk2dFontChar chr; if (_fontInst.useDictionary) { if (!_fontInst.charDict.ContainsKey(idx)) { idx = 0; } chr = _fontInst.charDict[idx]; } else { if (idx >= _fontInst.chars.Length) { idx = 0; // should be space } chr = _fontInst.chars[idx]; } if (inlineHatChar) { idx = '^'; } cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < str.Length - 1) { foreach (var k in _fontInst.kerning) { if (k.c0 == str[i] && k.c1 == str[i + 1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } maxWidth = Mathf.Max(cursorX, maxWidth); cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; return(new Vector2(maxWidth, cursorY)); }
public static void SetTextMeshIndices(int[] indices, int offset, int vStart, GeomData geomData, int target) { tk2dTextMeshData textMeshData = geomData.textMeshData; for (int i = 0; i < textMeshData.maxChars; i++) { indices[offset + (i * 6)] = vStart + (i * 4); indices[(offset + (i * 6)) + 1] = (vStart + (i * 4)) + 1; indices[(offset + (i * 6)) + 2] = (vStart + (i * 4)) + 3; indices[(offset + (i * 6)) + 3] = (vStart + (i * 4)) + 2; indices[(offset + (i * 6)) + 4] = vStart + (i * 4); indices[(offset + (i * 6)) + 5] = (vStart + (i * 4)) + 3; } }
public static int SetTextMeshGeom(Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset, GeomData geomData) { tk2dTextMeshData textMeshData = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; string formattedText = geomData.formattedText; meshTopColor = new Color32(0xff, 0xff, 0xff, 0xff); meshBottomColor = new Color32(0xff, 0xff, 0xff, 0xff); meshGradientTexU = ((float) textMeshData.textureGradient) / ((fontInst.gradientCount <= 0) ? ((float) 1) : ((float) fontInst.gradientCount)); curGradientCount = fontInst.gradientCount; float yAnchorForHeight = GetYAnchorForHeight(GetMeshDimensionsForString(geomData.formattedText, geomData).y, geomData); float num2 = 0f; float num3 = 0f; int num4 = 0; int targetStart = 0; for (int i = 0; (i < formattedText.Length) && (num4 < textMeshData.maxChars); i++) { tk2dFontChar ch; int key = formattedText[i]; bool flag = key == 0x5e; if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(key)) { key = 0; } ch = fontInst.charDict[key]; } else { if (key >= fontInst.chars.Length) { key = 0; } ch = fontInst.chars[key]; } if (flag) { key = 0x5e; } if (key == 10) { float lineWidth = num2; int targetEnd = num4; if (targetStart != num4) { float xAnchorForWidth = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, targetStart, targetEnd, xAnchorForWidth); } targetStart = num4; num2 = 0f; num3 -= (fontInst.lineHeight + textMeshData.lineSpacing) * textMeshData.scale.y; continue; } if (textMeshData.inlineStyling && (key == 0x5e)) { if (((i + 1) < formattedText.Length) && (formattedText[i + 1] == '^')) { i++; } else { i += HandleStyleCommand(formattedText.Substring(i + 1)); continue; } } pos[offset + (num4 * 4)] = new Vector3(num2 + (ch.p0.x * textMeshData.scale.x), (yAnchorForHeight + num3) + (ch.p0.y * textMeshData.scale.y), 0f); pos[(offset + (num4 * 4)) + 1] = new Vector3(num2 + (ch.p1.x * textMeshData.scale.x), (yAnchorForHeight + num3) + (ch.p0.y * textMeshData.scale.y), 0f); pos[(offset + (num4 * 4)) + 2] = new Vector3(num2 + (ch.p0.x * textMeshData.scale.x), (yAnchorForHeight + num3) + (ch.p1.y * textMeshData.scale.y), 0f); pos[(offset + (num4 * 4)) + 3] = new Vector3(num2 + (ch.p1.x * textMeshData.scale.x), (yAnchorForHeight + num3) + (ch.p1.y * textMeshData.scale.y), 0f); if (ch.flipped) { uv[offset + (num4 * 4)] = new Vector2(ch.uv1.x, ch.uv1.y); uv[(offset + (num4 * 4)) + 1] = new Vector2(ch.uv1.x, ch.uv0.y); uv[(offset + (num4 * 4)) + 2] = new Vector2(ch.uv0.x, ch.uv1.y); uv[(offset + (num4 * 4)) + 3] = new Vector2(ch.uv0.x, ch.uv0.y); } else { uv[offset + (num4 * 4)] = new Vector2(ch.uv0.x, ch.uv0.y); uv[(offset + (num4 * 4)) + 1] = new Vector2(ch.uv1.x, ch.uv0.y); uv[(offset + (num4 * 4)) + 2] = new Vector2(ch.uv0.x, ch.uv1.y); uv[(offset + (num4 * 4)) + 3] = new Vector2(ch.uv1.x, ch.uv1.y); } if (fontInst.textureGradients) { uv2[offset + (num4 * 4)] = ch.gradientUv[0] + new Vector2(meshGradientTexU, 0f); uv2[(offset + (num4 * 4)) + 1] = ch.gradientUv[1] + new Vector2(meshGradientTexU, 0f); uv2[(offset + (num4 * 4)) + 2] = ch.gradientUv[2] + new Vector2(meshGradientTexU, 0f); uv2[(offset + (num4 * 4)) + 3] = ch.gradientUv[3] + new Vector2(meshGradientTexU, 0f); } if (fontInst.isPacked) { Color32 color2 = channelSelectColors[ch.channel]; color[offset + (num4 * 4)] = color2; color[(offset + (num4 * 4)) + 1] = color2; color[(offset + (num4 * 4)) + 2] = color2; color[(offset + (num4 * 4)) + 3] = color2; } else { color[offset + (num4 * 4)] = meshTopColor; color[(offset + (num4 * 4)) + 1] = meshTopColor; color[(offset + (num4 * 4)) + 2] = meshBottomColor; color[(offset + (num4 * 4)) + 3] = meshBottomColor; } num2 += (ch.advance + textMeshData.spacing) * textMeshData.scale.x; if (textMeshData.kerning && (i < (formattedText.Length - 1))) { foreach (tk2dFontKerning kerning in fontInst.kerning) { if ((kerning.c0 == formattedText[i]) && (kerning.c1 == formattedText[i + 1])) { num2 += kerning.amount * textMeshData.scale.x; break; } } } num4++; } if (targetStart != num4) { float num12 = num2; int num13 = num4; float offsetX = GetXAnchorForWidth(num12, geomData); PostAlignTextData(pos, offset, targetStart, num13, offsetX); } for (int j = num4; j < textMeshData.maxChars; j++) { Vector3 vector2; Vector2 vector3; pos[(offset + (j * 4)) + 3] = vector2 = Vector3.zero; pos[(offset + (j * 4)) + 2] = vector2 = vector2; pos[offset + (j * 4)] = pos[(offset + (j * 4)) + 1] = vector2; uv[(offset + (j * 4)) + 3] = vector3 = Vector2.zero; uv[(offset + (j * 4)) + 2] = vector3 = vector3; uv[offset + (j * 4)] = uv[(offset + (j * 4)) + 1] = vector3; if (fontInst.textureGradients) { uv2[(offset + (j * 4)) + 3] = vector3 = Vector2.zero; uv2[(offset + (j * 4)) + 2] = vector3 = vector3; uv2[offset + (j * 4)] = uv2[(offset + (j * 4)) + 1] = vector3; } if (!fontInst.isPacked) { color[offset + (j * 4)] = color[(offset + (j * 4)) + 1] = meshTopColor; color[(offset + (j * 4)) + 2] = color[(offset + (j * 4)) + 3] = meshBottomColor; } else { Color32 color3; color[(offset + (j * 4)) + 3] = color3 = Color.clear; color[(offset + (j * 4)) + 2] = color3 = color3; color[offset + (j * 4)] = color[(offset + (j * 4)) + 1] = color3; } } return num4; }
public static int SetTextMeshGeom(Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; string formattedText = geomData.formattedText; meshTopColor = new Color32(255, 255, 255, 255); meshBottomColor = new Color32(255, 255, 255, 255); meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curGradientCount = fontInst.gradientCount; Vector2 dims = GetMeshDimensionsForString(geomData.formattedText, geomData); float offsetY = GetYAnchorForHeight(dims.y, geomData); float cursorX = 0.0f; float cursorY = 0.0f; int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < data.maxChars; ++i) { int idx = formattedText[i]; tk2dFontChar chr; bool inlineHatChar = (idx == '^'); if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(idx)) idx = 0; chr = fontInst.charDict[idx]; } else { if (idx >= fontInst.chars.Length) idx = 0; // should be space chr = fontInst.chars[idx]; } if (inlineHatChar) idx = '^'; if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= (fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^') { if (i + 1 < formattedText.Length && formattedText[i + 1] == '^') { ++i; } else { i += HandleStyleCommand(formattedText.Substring(i + 1)); continue; } } } pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = meshTopColor; color[offset + target * 4 + 1] = meshTopColor; color[offset + target * 4 + 2] = meshBottomColor; color[offset + target * 4 + 3] = meshBottomColor; } cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i+1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < data.maxChars; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } if (!fontInst.isPacked) { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = meshTopColor; color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = meshBottomColor; } else { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } } return target; }
/// <summary> /// Calculates the mesh dimensions for the given string /// and returns a width and height. /// </summary> public static Vector2 GetMeshDimensionsForString(string str, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; float maxWidth = 0.0f; float cursorX = 0.0f; float cursorY = 0.0f; bool ignoreNextCharacter = false; int target = 0; for (int i = 0; i < str.Length && target < data.maxChars; ++i) { if (ignoreNextCharacter) { ignoreNextCharacter = false; continue; } int idx = str[i]; if (idx == '\n') { maxWidth = Mathf.Max(cursorX, maxWidth); cursorX = 0.0f; cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^' && i + 1 < str.Length) { if (str[i + 1] == '^') { ignoreNextCharacter = true; } else { int cmdLength = 0; switch (str[i + 1]) { case 'c': cmdLength = 5; break; case 'C': cmdLength = 9; break; case 'g': cmdLength = 9; break; case 'G': cmdLength = 17; break; } i += cmdLength; continue; } } } bool inlineHatChar = (idx == '^'); // Get the character from dictionary / array tk2dFontChar chr; if (_fontInst.useDictionary) { if (!_fontInst.charDict.ContainsKey(idx)) idx = 0; chr = _fontInst.charDict[idx]; } else { if (idx >= _fontInst.chars.Length) idx = 0; // should be space chr = _fontInst.chars[idx]; } if (inlineHatChar) idx = '^'; cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < str.Length - 1) { foreach (var k in _fontInst.kerning) { if (k.c0 == str[i] && k.c1 == str[i+1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } maxWidth = Mathf.Max(cursorX, maxWidth); cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; return new Vector2(maxWidth, cursorY); }
static float GetYAnchorForHeight(float textHeight, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int heightAnchor = (int)data.anchor / 3; float lineHeight = (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; switch (heightAnchor) { case 0: return -lineHeight; case 1: { float y = -textHeight / 2.0f - lineHeight; if (_fontInst.version >= 2) { float ty = _fontInst.texelSize.y * data.scale.y; return Mathf.Floor(y / ty) * ty; } else return y; } case 2: return -textHeight - lineHeight; } return -lineHeight; }
static float GetXAnchorForWidth(float lineWidth, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int widthAnchor = (int)data.anchor % 3; switch (widthAnchor) { case 0: return 0.0f; // left case 1: // center { float x = -lineWidth / 2.0f; if (_fontInst.version >= 2) { float tx = _fontInst.texelSize.x * data.scale.x; return Mathf.Floor(x / tx) * tx; } return x; } case 2: return -lineWidth; // right } return 0.0f; }
public static float GetXAnchorForWidth(float lineWidth, GeomData geomData) { tk2dTextMeshData textMeshData = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; switch (((int) (textMeshData.anchor % TextAnchor.MiddleLeft))) { case 0: return 0f; case 1: { float num2 = -lineWidth / 2f; if (fontInst.version < 2) { return num2; } float num3 = fontInst.texelSize.x * textMeshData.scale.x; return (Mathf.Floor(num2 / num3) * num3); } case 2: return -lineWidth; } return 0f; }
public static int SetTextMeshGeom(Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; string formattedText = geomData.formattedText; meshTopColor = new Color32(255, 255, 255, 255); meshBottomColor = new Color32(255, 255, 255, 255); meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curGradientCount = fontInst.gradientCount; Vector2 dims = GetMeshDimensionsForString(geomData.formattedText, geomData); float offsetY = GetYAnchorForHeight(dims.y, geomData); float cursorX = 0.0f; float cursorY = 0.0f; int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < data.maxChars; ++i) { int idx = formattedText[i]; tk2dFontChar chr; bool inlineHatChar = (idx == '^'); if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(idx)) { idx = 0; } chr = fontInst.charDict[idx]; } else { if (idx >= fontInst.chars.Length) { idx = 0; // should be space } chr = fontInst.chars[idx]; } if (inlineHatChar) { idx = '^'; } if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= (fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^') { if (i + 1 < formattedText.Length && formattedText[i + 1] == '^') { ++i; } else { i += HandleStyleCommand(formattedText.Substring(i + 1)); continue; } } } pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = meshTopColor; color[offset + target * 4 + 1] = meshTopColor; color[offset + target * 4 + 2] = meshBottomColor; color[offset + target * 4 + 3] = meshBottomColor; } cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i + 1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < data.maxChars; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } if (!fontInst.isPacked) { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = meshTopColor; color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = meshBottomColor; } else { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } } return(target); }
public static Vector2 GetMeshDimensionsForString(string str, GeomData geomData) { tk2dTextMeshData textMeshData = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; float b = 0f; float a = 0f; float num3 = 0f; bool flag = false; int num4 = 0; for (int i = 0; (i < str.Length) && (num4 < textMeshData.maxChars); i++) { tk2dFontChar ch; if (flag) { flag = false; continue; } int key = str[i]; if (key == 10) { b = Mathf.Max(a, b); a = 0f; num3 -= (fontInst.lineHeight + textMeshData.lineSpacing) * textMeshData.scale.y; continue; } if ((textMeshData.inlineStyling && (key == 0x5e)) && ((i + 1) < str.Length)) { if (str[i + 1] == '^') { flag = true; } else { int num7 = 0; switch (str[i + 1]) { case 'C': num7 = 9; break; case 'G': num7 = 0x11; break; case 'c': num7 = 5; break; case 'g': num7 = 9; break; } i += num7; continue; } } bool flag2 = key == 0x5e; if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(key)) { key = 0; } ch = fontInst.charDict[key]; } else { if (key >= fontInst.chars.Length) { key = 0; } ch = fontInst.chars[key]; } if (flag2) { key = 0x5e; } a += (ch.advance + textMeshData.spacing) * textMeshData.scale.x; if (textMeshData.kerning && (i < (str.Length - 1))) { foreach (tk2dFontKerning kerning in fontInst.kerning) { if ((kerning.c0 == str[i]) && (kerning.c1 == str[i + 1])) { a += kerning.amount * textMeshData.scale.x; break; } } } num4++; } b = Mathf.Max(a, b); return new Vector2(b, num3 - ((fontInst.lineHeight + textMeshData.lineSpacing) * textMeshData.scale.y)); }
public static void GetTextMeshGeomDesc(this GeomData geomData, out int numVertices, out int numIndices) { numVertices = geomData.RequiredAllocatedCharacters * 4; numIndices = geomData.RequiredAllocatedCharacters * 6; }
public static void SetTextMeshGeom(this GeomData geomData, Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset) { tk2dTextMeshData data = geomData.TextMeshData; tk2dFontData fontInst = data.FontInst; tk2dColoredText formattedText = data.FormattedText; InlineStyler curStyler = new InlineStyler(); curStyler.meshTopColor = new Color32(255, 255, 255, 255); curStyler.meshBottomColor = new Color32(255, 255, 255, 255); curStyler.meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curStyler.curGradientCount = fontInst.gradientCount; Vector2 dims = data.GetMeshDimensionsForString(formattedText); float offsetY = data.GetYAnchorForHeight(dims.y); float cursorX = 0.0f; float cursorY = 0.0f; // target is required due to invisible '\n' character int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < geomData.CurrentAllocatedCharacters; ++i) { formattedText.ApplyColorCommand(curStyler, i); int idx = formattedText[i]; tk2dFontChar chr = fontInst.GetCharForIndex(idx, 0); if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= data.ActualLineSpaceHeight; } else { pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(curStyler.meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = curStyler.meshTopColor; color[offset + target * 4 + 1] = curStyler.meshTopColor; color[offset + target * 4 + 2] = curStyler.meshBottomColor; color[offset + target * 4 + 3] = curStyler.meshBottomColor; } cursorX += (chr.advance + data.Spacing) * data.TotalScale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i + 1]) { cursorX += k.amount * data.TotalScale.x; break; } } } target++; } } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < geomData.CurrentAllocatedCharacters; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } }
void CreateGeomDatas() { tempGeomDatasAsList.Clear(); for (int n = 0; n < Shapes.Length; n++) { tempGeomDatasAsList.Add(null); } dSpaceID bodySpaceID = scene.rootSpaceID; for (int nShape = 0; nShape < Shapes.Length; nShape++) { Shape shape = Shapes[nShape]; GeomData geomData = new GeomData(); geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; bool identityTransform = shape.Position == Vec3.Zero && shape.Rotation == Quat.Identity; // No offset transform. if (identityTransform) { geomData.spaceID = bodySpaceID; } //create geom switch (shape.ShapeType) { case Shape.Type.Box: { BoxShape boxShape = (BoxShape)shape; geomData.geomID = Ode.dCreateBox(geomData.spaceID, boxShape.Dimensions.X, boxShape.Dimensions.Y, boxShape.Dimensions.Z); } break; case Shape.Type.Sphere: { SphereShape sphereShape = (SphereShape)shape; geomData.geomID = Ode.dCreateSphere(geomData.spaceID, sphereShape.Radius); } break; case Shape.Type.Capsule: { CapsuleShape capsuleShape = (CapsuleShape)shape; geomData.geomID = Ode.dCreateCapsule(geomData.spaceID, capsuleShape.Radius, capsuleShape.Length); } break; case Shape.Type.Cylinder: { CylinderShape cylinderShape = (CylinderShape)shape; geomData.geomID = Ode.dCreateCylinder(geomData.spaceID, cylinderShape.Radius, cylinderShape.Length); } break; case Shape.Type.Mesh: { MeshShape meshShape = (MeshShape)shape; if (!Static) { if (!notSupportedMeshesLogInformed) { notSupportedMeshesLogInformed = true; Log.Warning("ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE."); } Log.Info("ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE."); //ignore shape continue; } //get mesh geometry from cache PhysicsWorld._MeshGeometry geometry = meshShape._GetMeshGeometry(); //ignore shape if (geometry == null) { Log.Info("ODEBody: Mesh is not initialized. ({0}).", meshShape.MeshName); continue; } ODEPhysicsWorld.MeshGeometryODEData data; if (geometry.UserData == null) { data = new ODEPhysicsWorld.MeshGeometryODEData(); //generate MeshGeometryODEData data data.triMeshDataID = Ode.dGeomTriMeshDataCreate(); data.verticesCount = geometry.Vertices.Length; data.indicesCount = geometry.Indices.Length; data.vertices = (IntPtr)Ode.dAlloc((uint) (Marshal.SizeOf(typeof(float)) * 3 * data.verticesCount)); data.indices = (IntPtr)Ode.dAlloc((uint) (Marshal.SizeOf(typeof(int)) * data.indicesCount)); unsafe { fixed(Vec3 *source = geometry.Vertices) { NativeUtils.CopyMemory(data.vertices, (IntPtr)source, data.verticesCount * sizeof(Vec3)); } fixed(int *source = geometry.Indices) { NativeUtils.CopyMemory(data.indices, (IntPtr)source, data.indicesCount * sizeof(int)); } } //build ode tri mesh data Ode.dGeomTriMeshDataBuildSingleAsIntPtr( data.triMeshDataID, data.vertices, Marshal.SizeOf(typeof(float)) * 3, data.verticesCount, data.indices, data.indicesCount, Marshal.SizeOf(typeof(int)) * 3); geometry.UserData = data; } else { data = (ODEPhysicsWorld.MeshGeometryODEData)geometry.UserData; } data.checkRefCounter++; geomData.meshGeometryODEData = data; geomData.geomID = Ode.dCreateTriMesh(geomData.spaceID, data.triMeshDataID, null, null, null); Ode.SetGeomTriMeshSetRayCallback(geomData.geomID); //unsafe //{ // float[] planes = new float[] // { // 1.0f ,0.0f ,0.0f ,0.25f, // 0.0f ,1.0f ,0.0f ,0.25f, // 0.0f ,0.0f ,1.0f ,0.25f, // -1.0f,0.0f ,0.0f ,0.25f, // 0.0f ,-1.0f,0.0f ,0.25f, // 0.0f ,0.0f ,-1.0f,0.25f // }; // float[] points = new float[] // { // 0.25f,0.25f,0.25f, // -0.25f,0.25f,0.25f, // 0.25f,-0.25f,0.25f, // -0.25f,-0.25f,0.25f, // 0.25f,0.25f,-0.25f, // -0.25f,0.25f,-0.25f, // 0.25f,-0.25f,-0.25f, // -0.25f,-0.25f,-0.25f, // }; // uint[] polygons = new uint[] // { // 4,0,2,6,4, // 4,1,0,4,5, // 4,0,1,3,2, // 4,3,1,5,7, // 4,2,3,7,6, // 4,5,4,6,7, // }; // float* nativePlanes = (float*)Ode.dAlloc( (uint)( sizeof( float ) * planes.Length ) ); // for( int n = 0; n < planes.Length; n++ ) // nativePlanes[ n ] = planes[ n ]; // uint planeCount = 6; // float* nativePoints = (float*)Ode.dAlloc( (uint)( sizeof( float ) * points.Length ) ); // for( int n = 0; n < points.Length; n++ ) // nativePoints[ n ] = points[ n ]; // uint pointCount = 8; // uint* nativePolygons = (uint*)Ode.dAlloc( (uint)( sizeof( uint ) * polygons.Length ) ); // for( int n = 0; n < polygons.Length; n++ ) // nativePolygons[ n ] = polygons[ n ]; // //ODEPhysicsWorld.MeshGeometryODEData data; // //if( geometry.UserData == null ) // //{ // // data = new ODEPhysicsWorld.MeshGeometryODEData(); // //} // geomData.geomID = Ode.dCreateConvex( geomData.spaceID, nativePlanes, // planeCount, nativePoints, pointCount, nativePolygons ); //} } break; } //add geom data to list tempGeomDatasAsList[nShape] = geomData; geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; // Use ODE's geom transform object. if (!identityTransform) { geomData.transformID = Ode.dCreateGeomTransform(bodySpaceID); } //set geom to body if (!Static) { if (geomData.transformID == dGeomID.Zero) { Ode.dGeomSetBody(geomData.geomID, bodyID); } else { Ode.dGeomSetBody(geomData.transformID, bodyID); } } if (geomData.transformID != dGeomID.Zero) { // Setup geom transform. Ode.dGeomTransformSetGeom(geomData.transformID, geomData.geomID); Ode.dQuaternion odeQuat; Convert.ToODE(shape.Rotation, out odeQuat); Ode.dGeomSetQuaternion(geomData.geomID, ref odeQuat); Ode.dGeomSetPosition(geomData.geomID, shape.Position.X, shape.Position.Y, shape.Position.Z); } // Set the GeomData reference for later use (e.g. in collision handling). geomData.shapeDictionaryIndex = scene.shapesDictionary.Add(geomData); dGeomID geomID = geomData.transformID != dGeomID.Zero ? geomData.transformID : geomData.geomID; Ode.CreateShapeData(geomID, bodyData, geomData.shapeDictionaryIndex, shape.ShapeType == Shape.Type.Mesh, shape.ContactGroup, shape.Hardness, shape.Restitution, shape.DynamicFriction, shape.StaticFriction); //shape pair flags Dictionary <Shape, ShapePairFlags> list = shape._GetShapePairFlags(); if (list != null) { foreach (KeyValuePair <Shape, ShapePairFlags> pair in list) { Shape otherShape = pair.Key; ShapePairFlags flags = pair.Value; if ((flags & ShapePairFlags.DisableContacts) != 0) { ODEBody otherBody = (ODEBody)otherShape.Body; GeomData otherGeomData = otherBody.GetGeomDataByShape(otherShape); if (otherGeomData != null) { dGeomID otherGeomID = (otherGeomData.transformID != dGeomID.Zero) ? otherGeomData.transformID : otherGeomData.geomID; Ode.SetShapePairDisableContacts(geomID, otherGeomID, true); } } } } } geomDatas = tempGeomDatasAsList.ToArray(); tempGeomDatasAsList.Clear(); if (Static) { UpdateStaticBodyGeomsTransform(); } }
void CreateGeomDatas() { tempGeomDatasAsList.Clear(); for( int n = 0; n < Shapes.Length; n++ ) tempGeomDatasAsList.Add( null ); dSpaceID bodySpaceID = scene.rootSpaceID; for( int nShape = 0; nShape < Shapes.Length; nShape++ ) { Shape shape = Shapes[ nShape ]; GeomData geomData = new GeomData(); geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; bool identityTransform = shape.Position == Vec3.Zero && shape.Rotation == Quat.Identity; // No offset transform. if( identityTransform ) geomData.spaceID = bodySpaceID; //create geom switch( shape.ShapeType ) { case Shape.Type.Box: { BoxShape boxShape = (BoxShape)shape; geomData.geomID = Ode.dCreateBox( geomData.spaceID, boxShape.Dimensions.X, boxShape.Dimensions.Y, boxShape.Dimensions.Z ); } break; case Shape.Type.Sphere: { SphereShape sphereShape = (SphereShape)shape; geomData.geomID = Ode.dCreateSphere( geomData.spaceID, sphereShape.Radius ); } break; case Shape.Type.Capsule: { CapsuleShape capsuleShape = (CapsuleShape)shape; geomData.geomID = Ode.dCreateCapsule( geomData.spaceID, capsuleShape.Radius, capsuleShape.Length ); } break; case Shape.Type.Cylinder: { CylinderShape cylinderShape = (CylinderShape)shape; geomData.geomID = Ode.dCreateCylinder( geomData.spaceID, cylinderShape.Radius, cylinderShape.Length ); } break; case Shape.Type.Mesh: { MeshShape meshShape = (MeshShape)shape; if( !Static ) { if( !notSupportedMeshesLogInformed ) { notSupportedMeshesLogInformed = true; Log.Warning( "ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE." ); } Log.Info( "ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE." ); //ignore shape continue; } //get mesh geometry from cache PhysicsWorld._MeshGeometry geometry = meshShape._GetMeshGeometry(); //ignore shape if( geometry == null ) { Log.Info( "ODEBody: Mesh is not initialized. ({0}).", meshShape.MeshName ); continue; } ODEPhysicsWorld.MeshGeometryODEData data; if( geometry.UserData == null ) { data = new ODEPhysicsWorld.MeshGeometryODEData(); //generate MeshGeometryODEData data data.triMeshDataID = Ode.dGeomTriMeshDataCreate(); data.verticesCount = geometry.Vertices.Length; data.indicesCount = geometry.Indices.Length; data.vertices = (IntPtr)Ode.dAlloc( (uint) ( Marshal.SizeOf( typeof( float ) ) * 3 * data.verticesCount ) ); data.indices = (IntPtr)Ode.dAlloc( (uint) ( Marshal.SizeOf( typeof( int ) ) * data.indicesCount ) ); unsafe { fixed( Vec3* source = geometry.Vertices ) { NativeUtils.CopyMemory( data.vertices, (IntPtr)source, data.verticesCount * sizeof( Vec3 ) ); } fixed( int* source = geometry.Indices ) { NativeUtils.CopyMemory( data.indices, (IntPtr)source, data.indicesCount * sizeof( int ) ); } } //build ode tri mesh data Ode.dGeomTriMeshDataBuildSingleAsIntPtr( data.triMeshDataID, data.vertices, Marshal.SizeOf( typeof( float ) ) * 3, data.verticesCount, data.indices, data.indicesCount, Marshal.SizeOf( typeof( int ) ) * 3 ); geometry.UserData = data; } else data = (ODEPhysicsWorld.MeshGeometryODEData)geometry.UserData; data.checkRefCounter++; geomData.meshGeometryODEData = data; geomData.geomID = Ode.dCreateTriMesh( geomData.spaceID, data.triMeshDataID, null, null, null ); Ode.SetGeomTriMeshSetRayCallback( geomData.geomID ); //unsafe //{ // float[] planes = new float[] // { // 1.0f ,0.0f ,0.0f ,0.25f, // 0.0f ,1.0f ,0.0f ,0.25f, // 0.0f ,0.0f ,1.0f ,0.25f, // -1.0f,0.0f ,0.0f ,0.25f, // 0.0f ,-1.0f,0.0f ,0.25f, // 0.0f ,0.0f ,-1.0f,0.25f // }; // float[] points = new float[] // { // 0.25f,0.25f,0.25f, // -0.25f,0.25f,0.25f, // 0.25f,-0.25f,0.25f, // -0.25f,-0.25f,0.25f, // 0.25f,0.25f,-0.25f, // -0.25f,0.25f,-0.25f, // 0.25f,-0.25f,-0.25f, // -0.25f,-0.25f,-0.25f, // }; // uint[] polygons = new uint[] // { // 4,0,2,6,4, // 4,1,0,4,5, // 4,0,1,3,2, // 4,3,1,5,7, // 4,2,3,7,6, // 4,5,4,6,7, // }; // float* nativePlanes = (float*)Ode.dAlloc( (uint)( sizeof( float ) * planes.Length ) ); // for( int n = 0; n < planes.Length; n++ ) // nativePlanes[ n ] = planes[ n ]; // uint planeCount = 6; // float* nativePoints = (float*)Ode.dAlloc( (uint)( sizeof( float ) * points.Length ) ); // for( int n = 0; n < points.Length; n++ ) // nativePoints[ n ] = points[ n ]; // uint pointCount = 8; // uint* nativePolygons = (uint*)Ode.dAlloc( (uint)( sizeof( uint ) * polygons.Length ) ); // for( int n = 0; n < polygons.Length; n++ ) // nativePolygons[ n ] = polygons[ n ]; // //ODEPhysicsWorld.MeshGeometryODEData data; // //if( geometry.UserData == null ) // //{ // // data = new ODEPhysicsWorld.MeshGeometryODEData(); // //} // geomData.geomID = Ode.dCreateConvex( geomData.spaceID, nativePlanes, // planeCount, nativePoints, pointCount, nativePolygons ); //} } break; } //add geom data to list tempGeomDatasAsList[ nShape ] = geomData; geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; // Use ODE's geom transform object. if( !identityTransform ) geomData.transformID = Ode.dCreateGeomTransform( bodySpaceID ); //set geom to body if( !Static ) { if( geomData.transformID == dGeomID.Zero ) Ode.dGeomSetBody( geomData.geomID, bodyID ); else Ode.dGeomSetBody( geomData.transformID, bodyID ); } if( geomData.transformID != dGeomID.Zero ) { // Setup geom transform. Ode.dGeomTransformSetGeom( geomData.transformID, geomData.geomID ); Ode.dQuaternion odeQuat; Convert.ToODE( shape.Rotation, out odeQuat ); Ode.dGeomSetQuaternion( geomData.geomID, ref odeQuat ); Ode.dGeomSetPosition( geomData.geomID, shape.Position.X, shape.Position.Y, shape.Position.Z ); } // Set the GeomData reference for later use (e.g. in collision handling). geomData.shapeDictionaryIndex = scene.shapesDictionary.Add( geomData ); dGeomID geomID = geomData.transformID != dGeomID.Zero ? geomData.transformID : geomData.geomID; Ode.CreateShapeData( geomID, bodyData, geomData.shapeDictionaryIndex, shape.ShapeType == Shape.Type.Mesh, shape.ContactGroup, shape.Hardness, shape.Restitution, shape.DynamicFriction, shape.StaticFriction ); //shape pair flags Dictionary<Shape, ShapePairFlags> list = shape._GetShapePairFlags(); if( list != null ) { foreach( KeyValuePair<Shape, ShapePairFlags> pair in list ) { Shape otherShape = pair.Key; ShapePairFlags flags = pair.Value; if( ( flags & ShapePairFlags.DisableContacts ) != 0 ) { ODEBody otherBody = (ODEBody)otherShape.Body; GeomData otherGeomData = otherBody.GetGeomDataByShape( otherShape ); if( otherGeomData != null ) { dGeomID otherGeomID = ( otherGeomData.transformID != dGeomID.Zero ) ? otherGeomData.transformID : otherGeomData.geomID; Ode.SetShapePairDisableContacts( geomID, otherGeomID, true ); } } } } } geomDatas = tempGeomDatasAsList.ToArray(); tempGeomDatasAsList.Clear(); if( Static ) UpdateStaticBodyGeomsTransform(); }