I needed this reader for my project so i have written pc2 point cache files reader that you can attach to your mesh, setup fps and let it run.
Right now this is the very early version and its not working on Android but it will soon, till then here is the video of it working and also the code for your viewing and using pleasure.
//
//POINT CACHE READER
//
//Created By: Dejan Omasta
//email: list3ner@gmail.com
//
//=================================================
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class PointCacheReader : MonoBehaviour
{
//
//POINT CACHE Vs
//
public string filePath;
struct PointCacheFile
{
public char[] signature;
public int fileVersion;
public int numPoints;
public float startFrame;
public float sampleRate;
public int numSamples;
public List<Vector3> vertexCoords;
}
PointCacheFile pcFile;
bool fileParsed = false;
//
//VERTEX POS Vs
//
public float fps = 24.0f;
Mesh mesh;
Vector3[] vertices;
int counter = 0;
int curFrame = 0;
float tempTime = 0.0f;
float timeMeasure = 0.0f;
// Use this for initialization
void Start ()
{
pcFile = new PointCacheFile();
ParsePCFile();
timeMeasure = 1 / fps;
mesh = this.GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
tempTime = Time.time;
}
// Update is called once per frame
void Update ()
{
}
void FixedUpdate()
{
if(Time.time > tempTime + timeMeasure)
{
if (fileParsed)
{
for (int x = 0; x < vertices.Length; x++)
{
vertices[x] = pcFile.vertexCoords[counter];
counter++;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
curFrame++;
if (curFrame == pcFile.numSamples)
{
curFrame = 0;
counter = 0;
}
}
tempTime = Time.time;
}
}
void ParsePCFile()
{
FileStream fs = new FileStream(filePath, FileMode.Open);
BinaryReader binReader = new BinaryReader(fs);
//
//SIGNATURE
//
pcFile.signature = new char[12];
pcFile.signature = binReader.ReadChars(12);
//
//FILE VERSION
//
pcFile.fileVersion = binReader.ReadInt32();
//
//NUMBER OF POINTS
//
pcFile.numPoints = binReader.ReadInt32();
//
//START FRAME
//
pcFile.startFrame = binReader.ReadSingle();
//
//SAMPLE RATE
//
pcFile.sampleRate = binReader.ReadSingle();
//
//NUMBER OF SAMPLES
//
pcFile.numSamples = binReader.ReadInt32();
//
//GET VERTEX COORDS
//
pcFile.vertexCoords = new List<Vector3>();
for (int i = 0; i < pcFile.numSamples; i++)
{
for (int x = 0; x < pcFile.numPoints; x++)
{
Vector3 vPos = new Vector3();
vPos.x = binReader.ReadSingle();
vPos.y = binReader.ReadSingle();
vPos.z = binReader.ReadSingle();
pcFile.vertexCoords.Add(vPos);
}
}
fileParsed = true;
}
}
Function ParsePCFile() parses the pc2 file in to PointCacheFile struct and yes all vertices are stored in to pcFile.vertexCoords List in the same order they are stored in pc2 file.
Here is Android update tested and working, this flag is happily running on my phone i don’t know for iPhone since i cant test it but i see no reason why it should not work.
This first PointCacheReader would also work on android the main limitation was deploying point cache file to your phone with the compiled project, i was thinking about making a feature where you put some web address and it downloads extra data like point caches from some web location but guys on #unity3d channel told me of cool way to move files with compiled game and I thank them for that so here is a little modified PointCacheAndReader
Just few steps you need to do that are different from previous procedure.
When you make your pc2 file change its extension in to *.bytes
Create folder Resources in your project
Drag 'n drop your file with changed extension in to Resources folder
That’s it, only thing you need to do is when you attach this script to your mesh just drag and drop your file from Resources folder to Cache File field in inspector, like you would assign any public variable (Transform, Material etc…)
And here is the code:
//
//POINT CACHE READER (Works on Android, probably iPhone too:))
//
//Created By: Dejan Omasta
//email: list3ner@gmail.com
//
//=================================================
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
public class PointCacheAndReader : MonoBehaviour
{
//
//POINT CACHE Vs
//
public TextAsset cacheFile;
struct PointCacheFile
{
public char[] signature;
public int fileVersion;
public int numPoints;
public float startFrame;
public float sampleRate;
public int numSamples;
public List<Vector3> vertexCoords;
}
PointCacheFile pcFile;
bool fileParsed = false;
//
//VERTEX POS Vs
//
public float fps = 24.0f;
Mesh mesh;
Vector3[] vertices;
int counter = 0;
int curFrame = 0;
float tempTime = 0.0f;
float timeMeasure = 0.0f;
// Use this for initialization
void Start ()
{
pcFile = new PointCacheFile();
Debug.Log("ZETZ - Calling ParsePCFile");
ParsePCFile();
timeMeasure = 1 / fps;
mesh = this.GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
tempTime = Time.time;
}
// Update is called once per frame
void Update ()
{
}
void FixedUpdate()
{
if(Time.time > tempTime + timeMeasure)
{
if (fileParsed)
{
for (int x = 0; x < vertices.Length; x++)
{
vertices[x] = pcFile.vertexCoords[counter];
counter++;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
curFrame++;
if (curFrame == pcFile.numSamples)
{
curFrame = 0;
counter = 0;
}
}
tempTime = Time.time;
}
}
void ParsePCFile()
{
MemoryStream ms = new MemoryStream(cacheFile.bytes);
BinaryReader binReader = new BinaryReader(ms);
//
//SIGNATURE
//
pcFile.signature = new char[12];
pcFile.signature = binReader.ReadChars(12);
//
//FILE VERSION
//
pcFile.fileVersion = binReader.ReadInt32();
//
//NUMBER OF POINTS
//
pcFile.numPoints = binReader.ReadInt32();
//
//START FRAME
//
pcFile.startFrame = binReader.ReadSingle();
//
//SAMPLE RATE
//
pcFile.sampleRate = binReader.ReadSingle();
//
//NUMBER OF SAMPLES
//
pcFile.numSamples = binReader.ReadInt32();
//
//GET VERTEX COORDS
//
pcFile.vertexCoords = new List<Vector3>();
for (int i = 0; i < pcFile.numSamples; i++)
{
for (int x = 0; x < pcFile.numPoints; x++)
{
Vector3 vPos = new Vector3();
vPos.x = binReader.ReadSingle();
vPos.y = binReader.ReadSingle();
vPos.z = binReader.ReadSingle();
pcFile.vertexCoords.Add(vPos);
}
}
fileParsed = true;
}
}
Awesome, I’m sorry if i ruined your plan wasn’t my intention.
Id love to hear what was your approach in transferring point cache file to android device, did you did it built in the APK like i did or have u used some other method?
I originally intended for it to be free, then I spent more and more time on it until it warranted a little payback ;). My vertexpainter was originally free until I started putting tons of time into it and needed a little return from spending time away from my kids.
Regarding the script:
At first, I created two byte files: One that translated all the positions and another that was sort of a key to tell which vertices matched up with which, and both sat in the resources folder; this worked on Android.
On Awake, the object would load the positions and key file into memory and worked great.
Then I thought the resources folder would get cluttered with a bunch of byte files so I changed it to load the positions into the gameObject itself with a @customEditor script. So now it does that without needing a separate byte file. You just drop your script on the gameObject, press “Load” and it loads the positions onto the game Object.
Will this wont work properly on any mesh that Unity alters on import due to normals or texture coords, as well as the axis system being changed depending on which 3d package the mesh came from? Also using unity normal recalc will give bad results for meshes with any kind of smoothing groups on, will you be able to solve these problems?
Don’t want to threadjack but mine accounts for mismatched vertex counts and different transforms and non centered pivots.
Have not tested with complex normals but shouldn’t be hard to figure out.
Well of course you implemented more options and spent more time on it, i really did this in few hours, most of the time spent finding structure of PC2 files not many docs on that, when i found it it was really quick maybe an hour of coding and testing.
Interesting approach, so you load it all in array or generic list and transfer it like that.
Well here is the thing, unity splits vertices depending on normals, 8 vertices box imported in unity will have 24 vertices, i think this all can be corrected using smoothing. But if your cache file has data for 8 vertices that’s a small bump, then you need extra step to check position of vertices in script and those that have same coordinates are actually one vertice and on all of them you can apply same transformation.
But since i did not have this problem in project i wrote this for i haven’t implemented that part at all, and i think if you use smoothing your vertices wont get split at all so no need for it.
As for coordspace, also possible to do the translation, you can just say x is y and so on also simple thing to implement and as i haven’t had need for it in my project haven’t implemented it because all meshes are custom made for this project and i have established workflow already so animation is done with idea to be used in unity, if you are using premade stuff animated for different purposes then you need to alter whats assigned to x, y and z.
Just make your own order out of it, i haven’t planned to publish this cache reader as commercial thing on store so haven’t implemented user friendly features to all this for you, just wanted to share this so it can help someone as it did me. Possibly if i have time i will implement this stuff.
If you made the mesh and animation with idea to use it in unity then you should not have any problems with this, if its something not made for that purpose then you need to test it first then possibly make some changes to script.
That is nice, do you match vertex position and apply same transforms on it?
I think this one could work with non centered pivots if its all cached like that why not.
I have tested it for example with bunch of pipes tangled going in all directions and ball animated as it goes trough pipes and as pipe gets thicker where ball passes, that was all rigged and animated in blender, then cached and worked nicely in unity.
ok i feel like a compleet idiot with an IQ of below zero but… how does this work…? and i don’t mean internally, just how do i get this to work :-s
i exported my mesh with a point cache modifier ontop from max (is that wrong for starters?) and then put you script on it… i even copied over the xml file to my assets folder and gave the script the path… but my flag just sits there all quite doing nothing
ok so i figured out is for a PC2 file not the xml, but still doesn’t do anything?