// toggles /*[System.NonSerialized] public bool drawAllFeet; [System.NonSerialized] public bool drawHeelToe; [System.NonSerialized] public bool drawFootBase; // children only true if parent is [System.NonSerialized] public bool drawTrajectories; [System.NonSerialized] public bool drawTrajectoriesProjected; [System.NonSerialized] public bool drawThreePoints; // at most one of these true [System.NonSerialized] public bool drawGraph; [System.NonSerialized] public bool normalizeGraph; // graph toggles [System.NonSerialized] public bool drawStanceMarkers; [System.NonSerialized] public bool drawBalanceCurve; [System.NonSerialized] public bool drawLiftedCurve; [System.NonSerialized] public float graphScaleH; [System.NonSerialized] public float graphScaleV; // toggles [System.NonSerialized] public bool drawFootPrints = true;*/ public void RenderGraphAll(MotionAnalyzerDrawOptions opt, int currentLeg) { //int currentLeg = opt.currentLeg; bool showAll = opt.drawAllFeet; bool drawFrames = (!showAll || currentLeg==0); // Helper variables int l = currentLeg; Transform ankleT = legC.legs[l].ankle; Transform toeT = legC.legs[l].toe; Vector3 graphSpan = graphMax-graphMin; Matrix4x4 objectMatrix = gameObject.transform.localToWorldMatrix; // Time variables float time = Util.Mod(gameObject.animation[animation.name].normalizedTime); int cycleIndex = GetIndexFromTime(time); float timeRounded = GetTimeFromIndex(cycleIndex); // Standard sizes float scale = gameObject.transform.localScale.z; float unit = cycleDistance * scale; float diamondSize = graphSpan.z*scale*0.03f; // Colors Color frameColor = new Color(0.7f, 0.7f, 0.7f, 1); Color ankleColor = new Color(0.8f, 0, 0, 1); Color toeColor = new Color(0, 0.7f, 0, 1); Color strongColor = new Color(0, 0, 0, 1); Color weakColor = new Color(0.7f, 0.7f, 0.7f, 1); if (showAll) { ankleColor = legC.legs[l].debugColor; toeColor = legC.legs[l].debugColor; strongColor = legC.legs[l].debugColor*0.5f + Color.black*0.5f; weakColor = legC.legs[l].debugColor*0.5f + Color.white*0.5f; } Color strongClear = strongColor; strongClear.a = 0.5f; GL.Begin( GL.QUADS ); // Key positions Vector3 footHeel = ankleT.position+Util.TransformVector( ankleT,legC.legs[l].ankleHeelVector ); Vector3 footToetip = toeT.position+Util.TransformVector( toeT,legC.legs[l].toeToetipVector ); Vector3 footbaseHeel = objectMatrix.MultiplyPoint3x4( cycles[l].samples[cycleIndex].footBase ); Vector3 footbaseToetip = objectMatrix.MultiplyPoint3x4( cycles[l].samples[cycleIndex].footBase +cycles[l].heelToetipVector ); // Draw foot heel and toetip if (opt.drawHeelToe) { DrawDiamond(footHeel, diamondSize, ankleColor); DrawDiamond(footToetip, diamondSize, toeColor); } // Draw foot balanced base if (opt.drawFootBase) { DrawDiamond(footbaseHeel, diamondSize, strongClear); DrawDiamond(footbaseToetip, diamondSize, strongClear); GL.End(); GL.Begin( GL.LINES ); DrawLine (footbaseHeel, footbaseToetip, strongColor); } GL.End(); // Draw foot step markers if (opt.drawFootPrints) { float cycleTime = Util.Mod(time-cycles[l].stanceTime+cycleOffset); Color c = weakColor*GetFootGrounding(l,cycleTime)+strongColor*(1-GetFootGrounding(l,cycleTime)); if (l==currentLeg) GL.Begin( GL.QUADS ); else GL.Begin( GL.LINES ); GL.Color(c); // Draw rectangles Vector3 pos = ( cycles[l].stancePosition +(cycleDirection*-cycleDistance*(Util.Mod(cycleTime+0.5f,1)-0.5f)) ); Vector3 down = Vector3.up*-0.5f*cycles[l].heelToetipVector.magnitude; GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+down) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+cycles[l].heelToetipVector) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+cycles[l].heelToetipVector+down) ); if (l!=currentLeg) { GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+cycles[l].heelToetipVector) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+cycles[l].heelToetipVector+down) ); GL.Vertex ( objectMatrix.MultiplyPoint3x4(pos+down) ); } GL.End(); } if (motionType!=MotionType.WalkCycle) { return; } if (opt.drawTrajectories) { GL.Begin( GL.LINES ); // Draw foot trajectories for (int i=0; i<samples*2; i++) { int j = Util.Mod(cycleIndex-i,samples); LegCycleSample sA = cycles[l].samples[j]; LegCycleSample sB = cycles[l].samples[Util.Mod(j-1,samples)]; float t1 = GetTimeFromIndex(i ); float t2 = GetTimeFromIndex(i+1); float driftA = 0; float driftB = 0; if (opt.normalizeGraph) { driftA = -t1*cycleDistance; driftB = -t2*cycleDistance; } Vector3 heelA = objectMatrix.MultiplyPoint3x4(sA.heel+driftA*cycleDirection); Vector3 heelB = objectMatrix.MultiplyPoint3x4(sB.heel+driftB*cycleDirection); Vector3 toetipA = objectMatrix.MultiplyPoint3x4(sA.toetip+driftA*cycleDirection); Vector3 toetipB = objectMatrix.MultiplyPoint3x4(sB.toetip+driftB*cycleDirection); Vector3 baseA = objectMatrix.MultiplyPoint3x4(sA.footBase+driftA*cycleDirection); Vector3 baseB = objectMatrix.MultiplyPoint3x4(sB.footBase+driftB*cycleDirection); if (opt.drawHeelToe) { DrawLine (heelA, heelB, ankleColor); DrawLine (toetipA, toetipB, toeColor); } if (opt.drawFootBase) { DrawLine (baseA, baseB, ((j%2==0) ? strongColor : weakColor)); } if (opt.drawTrajectoriesProjected) { // Draw foot center trajectory projected onto ground plane DrawLine ( objectMatrix.MultiplyPoint3x4( Util.ProjectOntoPlane(sA.heel+sA.toetip,Vector3.up)/2 + (legC.groundPlaneHeight-graphSpan.y)*Vector3.up ), objectMatrix.MultiplyPoint3x4( Util.ProjectOntoPlane(sB.heel+sB.toetip,Vector3.up)/2 + (legC.groundPlaneHeight-graphSpan.y)*Vector3.up ), strongColor ); } } GL.End(); if (opt.drawTrajectoriesProjected) { GL.Begin( GL.QUADS ); DrawDiamond( objectMatrix.MultiplyPoint3x4( Util.ProjectOntoPlane( cycles[l].samples[cycleIndex].heel +cycles[l].samples[cycleIndex].toetip, Vector3.up )/2 + (legC.groundPlaneHeight-graphSpan.y)*Vector3.up ), diamondSize, strongClear ); GL.End(); // Draw three points used to derive cycle direction if (opt.drawThreePoints) { for (int i=-1; i<=1; i++) { GL.Begin( GL.QUADS ); DrawDiamond( objectMatrix.MultiplyPoint3x4( cycles[l].cycleCenter + (legC.groundPlaneHeight-graphSpan.y)*Vector3.up + (i*cycles[l].cycleDirection*cycles[l].cycleScaling*0.5f) ), diamondSize, strongClear ); GL.End(); } // Draw axis line for movement. GL.Begin( GL.LINES ); DrawLine ( objectMatrix.MultiplyPoint3x4( cycles[l].cycleCenter +(legC.groundPlaneHeight-graphSpan.y)*Vector3.up - (cycles[l].cycleDirection*cycles[l].cycleScaling) ), objectMatrix.MultiplyPoint3x4( cycles[l].cycleCenter +(legC.groundPlaneHeight-graphSpan.y)*Vector3.up + (cycles[l].cycleDirection*cycles[l].cycleScaling) ), strongClear ); GL.End(); } } } if (opt.drawGraph) { GL.Begin( GL.LINES ); // Define graph areas Vector3 groundPlaneDown = legC.groundPlaneHeight*gameObject.transform.up*scale; float normExtend = 2*cycleDistance; if (!opt.normalizeGraph) normExtend = 0; Quaternion rot = gameObject.transform.rotation; Vector3 sideDir = rot * Quaternion.Euler(0,90,0)*cycleDirection; Vector3 upDir = rot * gameObject.transform.up; Vector3 cycleDir = rot * cycleDirection; Vector3 groundPos = gameObject.transform.position + groundPlaneDown; DrawArea graphZ = new DrawArea3D( new Vector3(-unit*0.5f, 0, 0), new Vector3(-unit*1.5f, scale, scale), Util.CreateMatrix(sideDir, upDir*opt.graphScaleV, cycleDir*opt.graphScaleH, groundPos) ); DrawArea graphBalance = new DrawArea3D( new Vector3(-unit*0.5f, graphSpan.y*scale*0.7f, 0), new Vector3(-unit*1.5f, graphSpan.y*scale*1.0f, 1), Util.CreateMatrix( sideDir, upDir+cycleDir, cycleDir-upDir, groundPos + cycleDir*graphMax.z*scale + upDir*graphSpan.y*scale ) ); DrawArea graphMarkers = new DrawArea3D( new Vector3(-unit*0.5f, graphSpan.y*scale*0.2f, 0), new Vector3(-unit*1.5f, graphSpan.y*scale*0.5f, 1), Util.CreateMatrix( sideDir, upDir+cycleDir, cycleDir-upDir, groundPos + cycleDir*graphMax.z*scale + upDir*graphSpan.y*scale ) ); // Draw frame if (drawFrames) { graphZ.DrawCube( new Vector3(0,0,graphMax.z), Vector3.right*2, Vector3.up*graphSpan.y, -Vector3.forward*(graphSpan.z+normExtend), frameColor ); } // Draw twice for (int i=0; i<2; i++) { // Draw stance time marker if (opt.drawStanceMarkers) { graphZ.DrawRect( new Vector3(Util.Mod(timeRounded-cycles[l].stanceTime+cycleOffset,1)+i,0,graphMax.z), Vector3.up*graphSpan.y, -Vector3.forward*(graphSpan.z+normExtend), strongColor ); } } if (opt.drawHeelToe) { DrawLine( ankleT.position+Util.TransformVector(ankleT,legC.legs[l].ankleHeelVector), graphZ.Point(new Vector3( 0, cycles[l].samples[cycleIndex].heel.y-legC.groundPlaneHeight, Vector3.Dot(cycles[l].samples[cycleIndex].heel,cycleDirection) )), ankleColor ); DrawLine( toeT.position+Util.TransformVector(toeT,legC.legs[l].toeToetipVector), graphZ.Point(new Vector3( 0, cycles[l].samples[cycleIndex].toetip.y-legC.groundPlaneHeight, Vector3.Dot(cycles[l].samples[cycleIndex].toetip,cycleDirection) )), toeColor ); } if (opt.drawFootBase) { DrawLine( footbaseHeel, graphZ.Point(new Vector3( 0, cycles[l].samples[cycleIndex].footBase.y-legC.groundPlaneHeight, Vector3.Dot(cycles[l].samples[cycleIndex].footBase,cycleDirection) )), Color.black ); } // Draw curves for (int i=0; i<samples*2; i++) { //int j = Util.Mod(cycles[l].stanceIndex+i,samples); int j = Util.Mod(cycleIndex-i,samples); LegCycleSample sA = cycles[l].samples[j]; LegCycleSample sB = cycles[l].samples[Util.Mod(j-1,samples)]; float t1 = GetTimeFromIndex(i ); float t2 = GetTimeFromIndex(i+1); float c1 = GetTimeFromIndex(Util.Mod(j -cycles[l].stanceIndex,samples)); float c2 = GetTimeFromIndex(Util.Mod(j-1-cycles[l].stanceIndex,samples)); float driftA = 0; float driftB = 0; if (opt.normalizeGraph) { driftA = -t1*cycleDistance; driftB = -t2*cycleDistance; } // Draw ankle and toe curves if (opt.drawHeelToe) { graphZ.DrawLine ( new Vector3(t1, sA.heel.y-legC.groundPlaneHeight, Vector3.Dot(sA.heel,cycleDirection)+driftA ), new Vector3(t2, sB.heel.y-legC.groundPlaneHeight, Vector3.Dot(sB.heel,cycleDirection)+driftB ), ankleColor ); graphZ.DrawLine ( new Vector3(t1, sA.toetip.y-legC.groundPlaneHeight, Vector3.Dot(sA.toetip,cycleDirection)+driftA ), new Vector3(t2, sB.toetip.y-legC.groundPlaneHeight, Vector3.Dot(sB.toetip,cycleDirection)+driftB ), toeColor ); } // Draw foot base curve if (opt.drawFootBase && j%2==0) { graphZ.DrawLine ( new Vector3(t1, sA.footBase.y-legC.groundPlaneHeight, Vector3.Dot(sA.footBase,cycleDirection)+driftA ), new Vector3(t2, sB.footBase.y-legC.groundPlaneHeight, Vector3.Dot(sB.footBase,cycleDirection)+driftB ), strongColor ); } // Draw foot balance curve (0=ankle, 1=toe) if (opt.drawBalanceCurve) { float balance = (sA.balance+sB.balance)/2; graphBalance.DrawLine ( new Vector3(t1,sA.balance,0), new Vector3(t2,sB.balance,0), toeColor*balance+ankleColor*(1-balance) ); } // Draw lift/liftoff and strike/land times if (opt.drawLiftedCurve) { float lifted = (GetFootGroundingOrig(l,c1)+GetFootGroundingOrig(l,c2))/2; graphMarkers.DrawLine ( new Vector3(t1,GetFootGroundingOrig(l,c1),0), new Vector3(t2,GetFootGroundingOrig(l,c2),0), strongColor*(1-lifted)+weakColor*lifted ); } } GL.End(); } }
public void RenderGraph(MotionAnalyzerDrawOptions opt) { CreateLineMaterial(); lineMaterial.SetPass( 0 ); if (opt.drawAllFeet) { for (int leg=0; leg<legs; leg++) { RenderGraphAll(opt,leg); } } else { RenderGraphAll(opt,opt.currentLeg); } }