Search Unity

Mesh Animator - Highly efficient animated crowds. For support, please use email.

Discussion in 'Assets and Asset Store' started by jschieck, Dec 7, 2014.

  1. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Hey everyone! My new asset is available in the asset store! With Mesh Animator you can animate thousands of meshes uniquely with minimal performance impact! Be sure to check out the performance comparison build and documentation pages, and feel free to reply in this thread or email me with any questions you may have. Happy animating!


    Asset Store Link
    Documentation


    Version 2.0 Release

    FPS Zombies Comparison

    Version 1.5 Release

    Basic Conversion Tutorial

    Mecanim vs. Mesh Animator Performance

    Version 2.0
    Full GPU instancing and custom shader support
    GPU animation texture bake mode
    Complete refactor
    New documentation!


    Version 1.5
    Improvements and Changes:

    Added support for exposing transforms! Have animated child transforms just like in the original object.
    Added support for multiple materials and submeshes!
    New support for root motion animations. None, baked, or apply the motion to the transform at runtime.
    Added support for the Optimized Game Objects option in the model importer.
    No more need for an animation controller for baking, just add your clips and bake!
    Baking humanoid rigs should work much, much better, on a wide variety of objects.
    Completely re-wrote mesh combining to be more efficient and accurate.
    Completely re-wrote crossfading code, increasing performance and reducing garbage allocations.
    Adding custom clips can now be done by selecting root assets.
    Added an option for skipping the last frame of animation for looping animations.

    Fixes:
    Greatly reduced garbage collection in mesh frame generation.
    Play() method is now case-sensitive.
    Phantom bake objects will no longer appear and remain in the scene after baking.
    Bounds for meshes while crossfading should now be correct.
     
    Last edited: Jul 13, 2020
    dyupa, Ignacii, XCO and 1 other person like this.
  2. BuildABurgerBurg

    BuildABurgerBurg

    Joined:
    Nov 5, 2012
    Posts:
    566
    nice work. The only negative is that it used double the memory. For mobiles that can be an issue. But in most cases it will be fine.

    Ill probably purchase soon

    Well done :)
     
  3. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    twobob likes this.
  4. BuildABurgerBurg

    BuildABurgerBurg

    Joined:
    Nov 5, 2012
    Posts:
    566
    "Memory usage is the same whether you are displaying 1 character, or 1000 characters"

    but the demo showed the memory increasing with the same mesh cloned.. right?

    are you saying if the one mesh is say 5mb then having 1000 would be 1000 x 5?
     
  5. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Memory usage increases as more frames of animation are requested and the meshes are created. Once all frames of animation are generated (which can be done on the fly or on instantiation), then the memory required for each clone won't increase, other than what's required for the GameObject and it's Components. Perhaps I could word that a little bit better.

    Let's assume a character takes 5MB for all of it's frames of animation, it won't take any more memory to display 1000 of those characters since all the meshes are shared between them.

    In the demo if you spawn one character and let it complete all it's animations, it will generate all it's animation meshes, and memory usage will stop increasing. Then spawning more of the same mesh won't increase the memory required from the Mesh Animator for that base mesh.

    Does that make sense? I tried to explain it the best I could.
     
    TokyoWarfareProject and twobob like this.
  6. BuildABurgerBurg

    BuildABurgerBurg

    Joined:
    Nov 5, 2012
    Posts:
    566
    yep you explained it perfectly :)

    I think I can get good use out of it.
     
  7. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Version 1.0.4 update
    Changes:
    • Animations can now be baked at any FPS
    • Each animation can be individually baked if needed
    • Now compatible with post-processed meshes
    • More performance improvements
    Fixes:
    • Fixed Crossfade method not working when calling from Javascript
    • Fixed animations not slowing down with slower playback speeds
    • Fixed some WrapModes not working as expected and not firing events
     
  8. GCatz

    GCatz

    Joined:
    Jul 31, 2012
    Posts:
    282
    Can you upload video of performance test in a mobile device ? (with crossfade)
     
  9. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Sure! I'll do it as soon as I'm home later today. Performance for crossfading is highly dependent on the number of vertices * number of meshes currently fading, since it has to Lerp all the positions per frame. I've got some major performance updates for crossfading coming in the next update that should greatly improve it's performance.
     
  10. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Here's a video I captured of it running on my Galaxy S4. I've submitted a new version to the asset store which has optional threaded crossfading for even better performance.

     
  11. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Version 1.0.5 is now live in the asset store with multi-threaded crossfading and significant crossfading performance improvements.
     
  12. GCatz

    GCatz

    Joined:
    Jul 31, 2012
    Posts:
    282
    Thanks for the recording, seems like a great asset, definitely a buy.
     
  13. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    this look like i like but how use him in action ?
     
  14. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Hey kilik! I'm not sure if I understand what you are asking, what do you mean by use him in action?
     
  15. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    in game what's it's possible to make for exemple collider and navmesh can be hard to script ? no ? on mobile
    it's can do on real time ? Each animation can be individually baked if needed < it's want's say i can shoot one unit l)
    working with blendshape < joke
    so yes how it's works it's merge skinmesh
     
  16. imtrobin

    imtrobin

    Joined:
    Nov 30, 2009
    Posts:
    1,548
    Must they all play the same animation at the same time or it can be different per character?
     
  17. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Yes they can all play different animations at different times, but they all pool their resources together for efficiency.
     
  18. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    500fish60Fps.JPG

    about 500 animals. with realtime avoidance. mesh animated. realtime. webplayer.
    Just a technology test. Rotation Lerping is a bit off, and half the fish accidentally transport a few thousand meters to the right (doh, var init val foof), I'll take a look at fixing it maybe.
    However this demonstrates the systems efficiency.

    This would simply not be possible with regular methods.
     
    Last edited: Apr 12, 2017
  19. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Looks great! Glad you were able to get everything working!
     
    twobob likes this.
  20. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
  21. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Hey everyone! A Unity 5 version has been added as well as several bug fixes! I've got a lot of more performance enhancements and additional improvements coming in the next release as well!
     
  22. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    We love your product. simple
    Buy this.

    You are limited by your imagination, the number of animation blends you want embedded and the amounts of models you might want to share that across..

    That might sounds limiting - it is not if you simply apply logic to the things you use it on.

    It is already amazing, and it's getting better? awesomer.

    Here are some pics where we used it recently in tests.

    newUnderseaLandscape.JPG
    bigFlcok.JPG
    it also can assist when other loads are high...

    AccidentalGeometery.JPG

    Yup that crazy mess is made of fish trails...
    AccidentalGeometryV.JPG

    and it does a nice job on simple character work.

    blinder :)

    Sheep.JPG
     
  23. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    how many take in space one backed animation please ?
     
  24. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    I think you mean "How much space does it take to bake in one animation"

    http://jacobschieck.com/projects/meshanimator/documentation/documentation.html#memory
    "With Mesh Animator, depending on the number of vertices, and number of frames in your animation, it is going to take up more memory than a traditional SkinnedMeshRenderer and Animator. Where you save is on the CPU. Finding a good balance between the two is important. If a character has 5k vertices and 20 animations each a few seconds long, it's not practical to use Mesh Animator."​

    The best use of Mesh Animator is with low-poly models with short animations. Each frame of animation is generated and copied from the base, this is why so much memory is needed for larger meshes and longer animations.

    A 4k triangle character (like in the example) takes up 500KB of memory. So to display a 1 second idle animation baked at 30fps, you would need approximately 15MB of memory. Memory usage is the same whether you are displaying 1 character, or 1000 characters. A character that has only 400 triangles takes 32KB of memory per mesh. So the same length animation would only take 960KB of memory. You can use this information to plan accordingly in your projects.


    Please note that these are the exact details from the previous versions docs, and may need updating. hope it helps
     
  25. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    In regards to disk space, it depends on the length of the animation and how many vertices the mesh has. So it's hard to estimate that. If you go off of raw data the formula would be (number of vertices * number of frames * 12) bytes for uncompressed animation. Multiplying by 12 since each float would be 4 bytes and a Vector3 is 3 floats. I've been experimenting with several compression algorithms to make that much smaller, but haven't found anything to get a small size and is fast enough to use at runtime on a large scale yet. It's still on my list of things to implement.
     
    twobob likes this.
  26. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    MeshAnimationCreator.CreateSnapshots () (at Assets/MeshAnimator/Editor/MeshAnimationCreator.cs:195)
    MeshAnimationCreator.OnGUI () (at Assets/MeshAnimator/Editor/MeshAnimationCreator.cs:166)

    I do what now when that happens?

    ModelImporter importer = (ModelImporter)AssetImporter.GetAtPath(s);

    upload_2015-4-14_3-50-12.png

    Seems valid? or am I being stupid, again.
     
  27. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Getting a "Cannot Cast" exception...
    I seem to think this is vaguely familiar but...

    any clues?

    I fired a copy to your email...
     
    Last edited: Apr 15, 2015
  28. c6u2

    c6u2

    Joined:
    Nov 15, 2013
    Posts:
    31
    Hi jschieck, I found there is no weapon on the mesh animator,but the original FBX model has it.Why?
     
  29. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    The example model has 2 separate meshes, one for the body and one for the weapon, separately skinned. If you wanted to have the weapon you'd have to bake it separately then sync the 2 mesh animators.
     
  30. c6u2

    c6u2

    Joined:
    Nov 15, 2013
    Posts:
    31
    You mean I should bake the weapon with it's animation alone, and sync the 2 mesh animators? But there have not skele information on the player's mesh animators,how to sync them?
     
  31. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Well I re-looked at the example and I forgot the weapon is not part of the SkinnedMeshRenderer. Ideally you'd either skin it to the skeleton, or use the following script.

    This script will attach any object to a face on the mesh animated object. It's relatively quick, and should give you what you need to attach a weapon or any other object to a mesh animator. It will also be included in the next release of MA.

    NOTE: In the current version of MA you must change the variable "currentFrame" in MeshAnimator.cs to public for this script to work. This change is also made in the next release of MA.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [ExecuteInEditMode]
    6. public class AttachObjectToFace : MonoBehaviour
    7. {
    8.     public MeshAnimator meshAnimator;
    9.     public int faceIndex;
    10.     public Vector3 offset;
    11.     public Vector3 rotationOffset;
    12.  
    13.     public bool drawFaceDebugInfo = false;
    14.     public Color debugColor = Color.black;
    15.  
    16.     private Transform mTransform;
    17.     private Transform mMeshAnimatorTransform;
    18.     private int[] triangles;
    19.     private Vector3[] vertices;
    20.  
    21.     void Awake()
    22.     {
    23.         mTransform = transform;
    24.         if (meshAnimator)
    25.         {
    26.             mMeshAnimatorTransform = meshAnimator.transform;
    27.             triangles = meshAnimator.GetComponent<MeshFilter>().sharedMesh.triangles;
    28.             vertices = meshAnimator.GetComponent<MeshFilter>().sharedMesh.vertices;
    29.         }
    30.     }
    31.     void LateUpdate()
    32.     {
    33.         if (meshAnimator)
    34.         {
    35.             if (!mMeshAnimatorTransform)
    36.                 mMeshAnimatorTransform = meshAnimator.transform;
    37.             if (triangles.Length == 0)
    38.             {
    39.                 triangles = meshAnimator.GetComponent<MeshFilter>().sharedMesh.triangles;
    40.                 vertices = meshAnimator.GetComponent<MeshFilter>().sharedMesh.vertices;
    41.             }
    42.  
    43.             faceIndex = Mathf.Clamp(faceIndex, 0, triangles.Length);
    44.             Vector3 v1, v2, v3;
    45.             if (Application.isPlaying == false || !meshAnimator || !meshAnimator.currentAnimation)
    46.             {
    47.                 v1 = vertices[triangles[faceIndex + 0]];
    48.                 v2 = vertices[triangles[faceIndex + 1]];
    49.                 v3 = vertices[triangles[faceIndex + 2]];
    50.             }
    51.             else
    52.             {
    53.                 v1 = meshAnimator.currentAnimation.GetFrame(meshAnimator.currentFrame)[triangles[faceIndex + 0]];
    54.                 v2 = meshAnimator.currentAnimation.GetFrame(meshAnimator.currentFrame)[triangles[faceIndex + 1]];
    55.                 v3 = meshAnimator.currentAnimation.GetFrame(meshAnimator.currentFrame)[triangles[faceIndex + 2]];
    56.             }
    57.             Vector3 faceCenter = Vector3.zero;
    58.  
    59.             faceCenter += v1;
    60.             faceCenter += v2;
    61.             faceCenter += v3;
    62.             faceCenter /= 3;
    63.  
    64.             Vector3 vec1 = v1 - v2;
    65.             Vector3 vec2 = v1 - v3;
    66.             Vector3 n = Vector3.Cross(vec1, vec2);
    67.             n.Normalize();
    68.             Quaternion rot = Quaternion.identity;
    69.             if (n != Vector3.zero)
    70.                 rot = Quaternion.LookRotation(n);
    71.             mTransform.position = mMeshAnimatorTransform.TransformPoint(faceCenter) + (rot * offset);
    72.             mTransform.rotation = rot;
    73.             mTransform.Rotate(rotationOffset);
    74.         }
    75.     }
    76. #if UNITY_EDITOR
    77.     void OnDrawGizmos()
    78.     {
    79.         if (drawFaceDebugInfo && meshAnimator)
    80.         {
    81.             GUIStyle style = new GUIStyle(GUI.skin.label);
    82.             style.fontStyle = FontStyle.Bold;
    83.             style.normal.textColor = debugColor;
    84.             int[] tris = meshAnimator.GetComponent<MeshFilter>().sharedMesh.triangles;
    85.             Vector3[] verts = meshAnimator.GetComponent<MeshFilter>().sharedMesh.vertices;
    86.             for (int i = 0; i < tris.Length; i += 3)
    87.             {
    88.                 Vector3 v1 = meshAnimator.transform.TransformPoint(verts[tris[i + 0]]);
    89.                 Vector3 v2 = meshAnimator.transform.TransformPoint(verts[tris[i + 1]]);
    90.                 Vector3 v3 = meshAnimator.transform.TransformPoint(verts[tris[i + 2]]);
    91.  
    92.                 Vector3 faceCenter = Vector3.zero;
    93.  
    94.                 faceCenter += v1;
    95.                 faceCenter += v2;
    96.                 faceCenter += v3;
    97.                 faceCenter /= 3;
    98.  
    99.                 UnityEditor.Handles.Label(faceCenter, i.ToString(), style);
    100.                 if (i == faceIndex)
    101.                 {
    102.                     Gizmos.color = debugColor;
    103.                     Gizmos.DrawLine(v1, v2);
    104.                     Gizmos.DrawLine(v2, v3);
    105.                     Gizmos.DrawLine(v1, v3);
    106.                 }
    107.             }
    108.         }
    109.     }
    110. #endif
    111. }
    112.  
     
    Last edited: May 3, 2015
  32. c6u2

    c6u2

    Joined:
    Nov 15, 2013
    Posts:
    31
    It's perfect! Thank you.
     
  33. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    For future Reference, You may want to tell people who have bought this to not use it on Mecanim animations in your project. As it turns them all to legacy animations and F*&$ up all the Animator settings... Im not mad, but just took the wind out of my sails for working on my project this weekend...
     
  34. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Hey. Sorry I didn't mention that anywhere in the docs. In the newest version I'll be submitting to the store this week, re-importing of assets is no longer needed, so it won't break your settings anymore.
     
  35. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    Hi Jacob
    So I have a character but im using animations from another character in mecanim. Is there a way to still bake these other Animations into my current character with mesh animator? If I Use original FBX model only the animations that come with it appear, and if I use a prefab it shows the extra animations but gives this error when I try to generate a snapshot.

    InvalidCastException: Cannot cast from source type to destination type.
    MeshAnimationCreator.CreateSnapshots () (at Assets/MeshAnimator/Editor/MeshAnimationCreator.cs:195)
    MeshAnimationCreator.OnGUI () (at Assets/MeshAnimator/Editor/MeshAnimationCreator.cs:166)
    System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)


    My End goal is that I will be using 3-4 Lod levels and hopefully with the lower Lods use mesh Animator Animations and the Closer LOD use Mecanim. End Goal is to have 50 -100 Low Poly Animated characters on a mobile platform.

    Any advice would be appreciated, thanks
     
  36. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Yes this is possible with the latest version. You can specify custom animation clips to be baked on whatever prefab or source FBX you want. I've PMed you a link to latest version in the meantime while it awaits approval in the asset store.
     
  37. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    awesome man thanks I'll check it out this evening
     
  38. ZeoWorks

    ZeoWorks

    Joined:
    Dec 13, 2012
    Posts:
    76
    Hello friend I intend to buy this soon.. But just to confirm;
    Are you able to use humanoid-animated models that use animations from other fbx models?
    If so I assume it does not use the mecanim interface? Instead it would work like this asset;
    https://www.assetstore.unity3d.com/en/#!/content/15156

    Please let me know soon, we intend to use humanoid-animated models.
    Many thanks! :)
     
  39. Raymond-H

    Raymond-H

    Joined:
    Mar 5, 2015
    Posts:
    3
    Hi jschieck
    your plugin is awesome and i plan to buy it, but before that could i take up your a bit time to ask a question?
    Does MeshAnimator keep skeleton child? Our game is a Action game, and the enemy in game have to find the appointed skeleton position to fire a bullet particle when he attack.
    Did you have any advice for this case? Thanks:)
     
  40. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Hey everyone! I've very excited to announce that version 1.2.0 is finally here! I've implemented a new compression that allows for much finer control and tuning from loss-less compression all the way down to voxelization. Here's a look!

    Accuracy = 0.001. Good for most animations. Use 0.0001 for even less compression.

    Accuracy = 0.1. A very low accuracy can be used to create animated models that look pixelated.



    Also included is the AttachToFace script which allows you to attach objects to any face on your character.



    Here's the change log along with some additional notes and a tutorial video:

    Changelog:
    OLD BAKED ANIMATION WILL NO LONGER PLAY
    New features:

    New compression algorithm, allowing for much smaller animation sizes, and the creation of voxelized characters.
    Added the ability to add custom clips to bake.
    Added an AttachObjectToFace for attaching an object to a specific mesh face.

    Changes:
    Baking should be much, much faster now, and work with any GameObject and not just FBX files.
    Lots of bug fixes.

    Here's a quick video showing how the get the above results for voxelized characters.
     
    hopeful likes this.
  41. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Sorry for the late reply, for some reason I never got a notification about it. The answer is yes, you can use other animations, but you need to bake each one separately. So even though they share the same source animation, each one would generate it's own MeshAnimation once baked.
     
  42. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    No it does not keep the skeleton. What you can do though is use the AttachToFace script and attach an empty GameObject to the mesh where you would like to the bullet to hit.
     
  43. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    708
    Awesome. Going to be actually trying to use this asset in my game soon i hope. Looking forward to testing this version out.
     
  44. Raymond-H

    Raymond-H

    Joined:
    Mar 5, 2015
    Posts:
    3
    Thx for your reply! Maybe the AttachToFace script could solve our project problem, i'll try it.
     
  45. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    lastAssetName A string I added to the function

    blah blah
    Code (CSharp):
    1.  PrefabUtility.CreatePrefab(assetFolder + asset.name + ".prefab", asset, ReplacePrefabOptions.ReplaceNameBased);
    2. lastAssetName = asset.name;
    blah blah
    Code (CSharp):
    1.  EditorUtility.DisplayDialog("Mesh Animator", string.Format
    2.     ("Baked "
    3.       + assetFolder
    4.       + lastAssetName
    5.       + ".prefab {0} animation{1} successfully!",
    6.   clips.Count,
    7.   clips.Count > 1 ? "s" : string.Empty),
    8. "OK");
    upload_2015-8-28_10-9-8.png

    Helpful. ;)

    (I had no idea :p)

    EDIT: And yep I read the docs... Just didn't seem to find it the first time I did it HAH
     
    Last edited: Aug 28, 2015
  46. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Quick point. How do I constrain root motion?

    I checked in the anim import settings and they appear to be constrained?

    upload_2015-8-28_11-1-5.png


    I appear to be getting Z movement it in my resultant mesh but not in the preview window, nor when I use that animation unbaked.

    upload_2015-8-28_10-59-34.png

    Any clues ? :)
     
  47. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    I am pretty sure I have root motion disabled now in

    upload_2015-8-28_11-11-3.png

    and the pose is correct I believe, with baked x/z

    upload_2015-8-28_11-14-4.png

    perhaps it is silently not overwriting previous efforts?
    I will clear it down.
     
  48. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    so I tried another model...

    He became very mangled and his presence stretched out long into floating point error oblivion in a cyclical way.

    upload_2015-8-28_11-25-43.png

    Hmmmmm.

    Less Compression did not help

    upload_2015-8-28_11-30-7.png

    Custom Clip problem maybe? The clip is valid and works prior to conversion..

    upload_2015-8-28_11-33-9.png
     
    Last edited: Aug 28, 2015
  49. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    Interesting... I understand what's going on, but it's kind of hard to diagnose without a copy of the model so I can really take a look at it. Could you send both the guy and the girl to me in a PM or email it to me? I'll take a look at it right away and get back to you with a fix for it.
     
  50. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    on it.

    files sent