HI ,I am working on a MonoGame.Forms project but i have a proplem with the process memory that it keeps icreasing in steady rate with time even without doing anything , which will lead the graphic devise to be suspended after around 40min or so .
the basic idea of my editor that it loads a json file that contains a skeletal structure then i deserialize(convert) the json into a list of bones the display the armature in my ViewPort (monogame) class
I posted on a the same problem befor but the increase of the memory back then was hiegh and fast
i was told that happend because i was creating a new basiceffict each time i draw somthing
but now i made sure to create only one in DrawWorld ,
but now the rate of increase in memory is not affected by loading a file , Whether there is a file is loaded or not the memory will keep increasing , also me editor can load fbx files but that dosnt affect
the memory that much.
it reached 700mb after like 10-15 min without touching it .
public static ViewPort mono;
private GraphicsDeviceManager graphics;
GraphicsDevice graphicsDevice;
SpriteBatch spriteBatch;
private BasicEffect basicEffect;
public static Matrix WorldMatrix= Matrix.CreateWorld(Vector3.Zero,Vector3.Forward,Vector3.Up);
public static Matrix Projection;
public static Matrix View;
public static VertexPositionColor[] vertices = new VertexPositionColor[0];
public static VertexPositionColor[] triVertices = new VertexPositionColor[0];
protected override void Initialize()
{
BoneJsonEditor.Include.MySFformat.mono = this;
_stopwatch = Stopwatch.StartNew();
spriteBatch = new SpriteBatch(GraphicsDevice);
this.graphicsDevice = GraphicsDevice;
base.Initialize();
}
protected override void Update(GameTime gameTime)
{
Form1.UpdateSelected();
DisplayOption.UpdateBool();
MySFCamera(gameTime);
base.Update(gameTime);
}
protected override void Draw()
{
base.Draw();
GraphicsDevice.Clear(MegaGray);
// Measure the elapsed time since the last frame
long elapsedTicks = _stopwatch.ElapsedTicks - _lastFrameTime;
float elapsedSeconds = (float)elapsedTicks / Stopwatch.Frequency;
_lastFrameTime = _stopwatch.ElapsedTicks;
// Measure the current memory usage
long memoryUsage = GC.GetTotalMemory(false);
long processMemoryUsage = Process.GetCurrentProcess().WorkingSet64;
Editor.spriteBatch.Begin();
DrawWorld();
GraphicsDevice.BlendState = BlendState.AlphaBlend;
DrawAxes();
Editor.spriteBatch.DrawString(Editor.Font, $"Memory: {(processMemoryUsage / 1024f / 1024f):F2} MB", new Vector2(GraphicsDevice.Viewport.Width - 150, 10), Color.White);
GraphicsDevice.BlendState = BlendState.AlphaBlend;
BoneDisplay();
GraphicsDevice.BlendState = BlendState.AlphaBlend;
if (isShow3dEnabled)
{
if (isMdlTriangleEnabled)
{
renderMode = RenderMode.Triangle;
}
else if (isMdlLineEnabled)
{
renderMode = RenderMode.Line;
}
else
{
renderMode = RenderMode.BothNoTex;
}
DrawModel();
}
KeyboardState state = Keyboard.GetState();
if (!isDialogOpen && state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.V))
{
checkVerticesSilent();
Editor.spriteBatch.End(); // End sprite batch before displaying form
displayVerticesInfo();
Editor.spriteBatch.Begin(); // Begin sprite batch again after form is closed
}
Editor.spriteBatch.End();
_lastMemoryUsage = memoryUsage;
_lastProcessMemoryUsage = processMemoryUsage;
}
my update method have only my camera and updates some display options like diplaying bones as a stick or a octahedral etc, which is controlled by another form
the DrawWorld method sets up my basiceffict and world matrices
the DrawAxis and DrawGround draws XYZ and grid lines
private void DrawWorld()
{
var cameraPosition = new Vector3(cameraX + offsetX, cameraY + offsetY, cameraZ + offsetZ);
var cameraLookAtVector = new Vector3(centerX + offsetX, centerY + offsetY, centerZ + offsetZ);
var cameraUpVector = Vector3.UnitY;
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.View = Matrix.CreateLookAt(
cameraPosition, cameraLookAtVector, cameraUpVector);
basicEffect.VertexColorEnabled = true;
float aspectRatio =
(float)GraphicsDevice.Viewport.AspectRatio
;
float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
float nearClipPlane = 0.1f;
float farClipPlane = 200;
basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
fieldOfView, aspectRatio, nearClipPlane, farClipPlane);
basicEffect.VertexColorEnabled = true;
basicEffect.World = WorldMatrix;
Projection = basicEffect.Projection;
View = basicEffect.View;
BlendState blendState = new BlendState();
DepthStencilState depthBufferState = new DepthStencilState();
depthBufferState.DepthBufferEnable = true;
depthBufferState.DepthBufferFunction = CompareFunction.LessEqual;
GraphicsDevice.DepthStencilState = depthBufferState;
basicEffect.CurrentTechnique.Passes[0].Apply();
}
private void DrawAxes()
{
float Axis = 20;
Vector3 xAxis = new Vector3(Axis, 0, 0);
Vector3 yAxis = new Vector3(0, Axis, 0);
Vector3 zAxis = new Vector3(0, 0, Axis);
VertexPositionColor[] AXvertices = new VertexPositionColor[6];
int[] indices = { 0, 1, 2, 3, 4, 5 };
AXvertices[0].Position = Vector3.Zero;
AXvertices[0].Color = Color.Red;
AXvertices[1].Position = xAxis;
AXvertices[1].Color = Color.Red;
AXvertices[2].Position = Vector3.Zero;
AXvertices[2].Color = Color.Green;
AXvertices[3].Position = yAxis;
AXvertices[3].Color = Color.Green;
AXvertices[4].Position = Vector3.Zero;
AXvertices[4].Color = Color.Blue;
AXvertices[5].Position = zAxis;
AXvertices[5].Color = Color.Blue;
GraphicsDevice.DrawUserIndexedPrimitives(
Microsoft.Xna.Framework.Graphics.PrimitiveType.LineList,
AXvertices,
0,
AXvertices.Length,
indices,
0,
indices.Length / 2);
DrawGround();
}
then the BoneDisplay () sets up the bones to be displayed
public void BoneDisplay ()
{
List<Bone> Bones = Form1.Skeleton;
Transform3D[] boneTrans = new Transform3D[Bones.Count];
for (int i = 0; i < Bones.Count; i++)
{
boneTrans[i] = new Transform3D();
boneTrans[i].rotOrder = rotOrder;
boneTrans[i].position = new Vector3D(Bones[i].Translation);
boneTrans[i].setRotationInRad(new Vector3D(Bones[i].Rotation));
boneTrans[i].scale = new Vector3D(Bones[i].Scale);
if (Bones[i].ParentIndex >= 0)
{
boneTrans[i].parent = boneTrans[Bones[i].ParentIndex];
Vector3D head = boneTrans[i].getGlobalOrigin();
if (boneTrans[Bones[i].ParentIndex] != null)
{
Vector3D tail = boneTrans[Bones[i].ParentIndex].getGlobalOrigin();
Vector3 Head = new Vector3(head.X, head.Y, head.Z);
Vector3 Tail = new Vector3(tail.X, tail.Y, tail.Z);
RasterizerState rasterizerState = new RasterizerState();
if (i == Form1.selectedbone)
{
bonecolor = Color.Yellow;
Snap.oldPosition = Head;
Matrix3D posTrans = Matrix3D.generateTranslationMatrix(head.X, head.Y, head.Z);
Matrix3D parentRot = boneTrans[i].parent.getGlobalRotation();
Matrix3D Rot = boneTrans[i].getGlobalRotation();
Matrix3D invRot = Matrix3D.invert(Rot);
Matrix3D World = Matrix3D.CreateWorld(new Vector3D(0, 0, 0), new Vector3D(0, 0, -1), new Vector3D(0, 1, 0));
Matrix3D boneWorld = posTrans * parentRot;
Matrix parentRotation = Matrix3D.MatrixConv(Rot);
// Matrix boneWorldxna = Matrix3D.MatrixConv(boneWorld);
KeyboardState state = Keyboard.GetState();
if (state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.F))
{
// Get the head and tail as strings
string headStr = $"Head: ({head.X}, {head.Y}, {head.Z})";
string tailStr = $"Tail: ({tail.X}, {tail.Y}, {tail.Z})";
// Get the parent rotation as a string
string parentRotationStr = "";
if (parentRotation != null)
{
Matrix Rotation = parentRotation;
parentRotationStr = "Bone Rotation:\n";
parentRotationStr += $"M = [{Rotation.M11}, {Rotation.M12}, {Rotation.M13}, {Rotation.M14}; ";
parentRotationStr += $"{Rotation.M21}, {Rotation.M22}, {Rotation.M23}, {Rotation.M24}; ";
parentRotationStr += $"{Rotation.M31}, {Rotation.M32}, {Rotation.M33}, {Rotation.M34}; ";
parentRotationStr += $"{Rotation.M41}, {Rotation.M42}, {Rotation.M43}, {Rotation.M44}];";
}
// Show the message box
string message = $"{headStr}\n{tailStr}\n{parentRotationStr}";
System.Windows.Forms.MessageBox.Show(message, "Bone Information");
}
Vector3D mxAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0.1f, 0, 0));
// Vector3 mxAxis3 = Vector3.Transform(new Vector3(0.1f, 0, 0), boneWorldxna);
Vector3D myAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0.1f, 0));
// Vector3 myAxis3 = Vector3.Transform(new Vector3(0, 0.1f, 0), boneWorldxna);
Vector3D mzAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0, 0.1f));
//Vector3 mzAxis3 = Vector3.Transform(new Vector3(0, 0, 0.1f), boneWorldxna);
Vector3D Origin3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0, 0));
// Vector3 Origin3 = Vector3.Transform( new Vector3(0, 0, 0), boneWorldxna);
VertexPositionColor[] MNvertices = new VertexPositionColor[6];
int[] indices = { 0, 1, 2, 3, 4, 5 };
Vector3 mxAxis = new Vector3(mxAxis3.X, mxAxis3.Y, mxAxis3.Z);
Vector3 myAxis = new Vector3(myAxis3.X, myAxis3.Y, myAxis3.Z);
Vector3 mzAxis = new Vector3(mzAxis3.X, mzAxis3.Y, mzAxis3.Z);
Vector3 Origin = new Vector3(Origin3.X, Origin3.Y, Origin3.Z);
MNvertices[0].Position = Origin;
MNvertices[0].Color = Color.Red;
MNvertices[1].Position = mxAxis;
MNvertices[1].Color = Color.Red;
MNvertices[2].Position = Origin;
MNvertices[2].Color = Color.Green;
MNvertices[3].Position = myAxis;
MNvertices[3].Color = Color.Green;
MNvertices[4].Position = Origin;
MNvertices[4].Color = Color.Blue;
MNvertices[5].Position = mzAxis;
MNvertices[5].Color = Color.Blue;
GraphicsDevice.DrawUserIndexedPrimitives(Microsoft.Xna.Framework.Graphics.PrimitiveType.LineList, MNvertices, 0, MNvertices.Length, indices, 0, indices.Length / 2);
}
else
{
bonecolor = Color.White;
}
if (isStickDisEnabled)
{
DrawStick(Head, Tail, bonecolor , rasterizerState);
}
else if (isOktaSolDisEnabled || isOktaWireDisEnabled)
{
DrawOctahedralBone(Tail, Head, bonecolor, rasterizerState);
}
}
}
}
}
private void DrawStick(Vector3 upperHead, Vector3 ParentPos, Color color , RasterizerState rasterizerState)
{
GraphicsDevice.BlendState = BlendState.AlphaBlend;
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;
VertexPositionColor[] lineVertices = new VertexPositionColor[2];
lineVertices[0].Position = ParentPos;
lineVertices[0].Color = Color.Crimson;
lineVertices[1].Position = upperHead;
lineVertices[1].Color = Color.Crimson;
short[] lineIndices = new short[2];
lineIndices[0] = 0;
lineIndices[1] = 1;
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, lineVertices, 0, 2, lineIndices, 0, 1);
GraphicsDevice.BlendState = BlendState.Additive;
Color colorWithOpacity = Color.FromNonPremultiplied(color.R, color.G, color.B, Alpha );
Vector3 position = upperHead;
int sphereResolution = 12;
int numVertices = (sphereResolution + 1) * (sphereResolution + 1);
VertexPositionColor[] sphereVertices = new VertexPositionColor[numVertices];
int index = 0;
float radius = 0.005f;
for (int i = 0; i <= sphereResolution; i++)
{
float latitude = ((float)i / (float)sphereResolution) * MathHelper.Pi - MathHelper.Pi;
for (int j = 0; j <= sphereResolution; j++)
{
float longitude = ((float)j / (float)sphereResolution) * MathHelper.TwoPi;
sphereVertices[index].Position = new Vector3((float)Math.Sin(latitude) * (float)Math.Cos(longitude), (float)Math.Cos(latitude), (float)Math.Sin(latitude) * (float)Math.Sin(longitude)) * radius + position;
sphereVertices[index].Color = colorWithOpacity;
index++;
}
}
int numIndices = sphereResolution * sphereResolution * 6;
short[] sphereIndices = new short[numIndices];
index = 0;
for (int i = 0; i < sphereResolution; i++)
{
for (int j = 0; j < sphereResolution; j++)
{
sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j);
sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j);
sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j + 1);
sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j);
sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j + 1);
sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j + 1);
}
}
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, sphereVertices, 0, numVertices, sphereIndices, 0, numIndices / 3);
}