[Closed] Howcan I detect pc2 point cache file is empty?
I want to avoid loading empty point cache file.
What would be the best way to detect if point cache file is empty?
The following is a method I use to query various information from PC2 files. It’s generally based on the PointCache code in the SDK examples.
def_visible_primitive(GetPointCacheFileInfo, "GetPointCacheFileInfo");
Value* GetPointCacheFileInfo_cf(Value **arg_list, int count)
{
check_arg_count(GetPointCacheFileInfo, 1, count);
MSTR filename = arg_list[0]->to_string();
HANDLE hFile = ::CreateFile(filename.data(),
GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, // allow file to be overwritten or deleted out from under us!
0,
OPEN_EXISTING,
0,
NULL);
if (!hFile)
{
return &undefined;
}
::SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
char m_cacheSignature[12];
int m_cacheVersion;
int m_cacheNumPoints;
int m_cacheNumSamples;
float m_cacheStartFrame;
float m_cacheSampleRate;
DWORD numRead;
if (!ReadFile(hFile, &m_cacheSignature, sizeof(m_cacheSignature), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
if (!ReadFile(hFile, &m_cacheVersion, sizeof(m_cacheVersion), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
if (!ReadFile(hFile, &m_cacheNumPoints, sizeof(m_cacheNumPoints), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
if (!ReadFile(hFile, &m_cacheStartFrame, sizeof(m_cacheStartFrame), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
if (!ReadFile(hFile, &m_cacheSampleRate, sizeof(m_cacheSampleRate), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
if (!ReadFile(hFile, &m_cacheNumSamples, sizeof(m_cacheNumSamples), &numRead, NULL) || numRead == 0) { ::CloseHandle(hFile); return &undefined; }
::CloseHandle(hFile);
one_typed_value_local(Array* result);
vl.result = new Array(4);
vl.result->append(Float::intern((float)m_cacheStartFrame));
vl.result->append(Float::intern((float)m_cacheSampleRate));
vl.result->append(Integer::intern(m_cacheNumSamples));
vl.result->append(Integer::intern(m_cacheNumPoints));
return_value(vl.result);
}
I usually just query the file size of the cache file. Here is a sample of the main FN for a cache cycle tool I wrote to cache out selected geo.
PCMod=Point_Cache()
addmodifier CREAM._objAr[i] PCMod
ModFilename=CREAM._CacheDir+CREAM._objAr[i].name
PCMod.filename=(ModFilename+".xml")
cacheOps.RecordCache PCMod
fsize=getfilesize (CREAM._cachedir+CREAM._objAr[i].name+".mc")
After applying a cache mod and simming it, it reads the size of the cache file.
if fsize>1000 then
(
collapsestack CREAM._objAr[i]
addmodifier CREAM._objAr[i] PCMod
PCMod.filename=(ModFilename+".xml")
append CREAM._cacheAr[1] CREAM._objAr[i].name
)
else
(
deletemodifier CREAM._objAr[i] PCMod
deletefile (ModFilename+".xml")
deletefile (ModFilename+".mc")
append CREAM._cacheAr[2] CREAM._objAr[i].name
)
If the cache file size is larger than 1kb (what I have found the size of a blank cache file to be), then it collapses the stack and adds a new cache mod and plugs in the cache file, otherwise it deletes the cache mod, the xml file and the mc file. The last line in each just appends an array that is called by a messagebox to let me know what has been cached and what hasn’t.
A Maxscript version returning similar data to Lo’s SDK sample
/*
[NAME]: GetPCFileData
[FUNCTION]:
function to retrieve extra PC2 data from files
[ARGUMENTS]:
<STRING> PCMod:A pointcache file path
<NODE> PCMod: A pointcache modifier
[RETURN]:
<ARRAY>
-- Return Structure
-- 2 NumPoints
-- 3 Start
-- 4 SampleRate
-- 5 Evaluations
-- 6 End
*/
fn GetPCFileData PCMod =
(
if Classof PCMod == string then PCFile = PCMod else PcFile = PCMod.filename
if doesfileexist PCFile then
(
FileError = false
PCArrayData = #()
PCArrayData[6] = 0
afStream = fOpen PCFile "rb"
if ((ReadString afStream) != "POINTCACHE2") then FileError = true else PCArrayData[1] = "POINTCACHE2"
if ((ReadLong afStream) != 1 ) then FileError = true
if not FileError then
(
--NumPoints
PCArrayData[2] = ReadLong afStream
--Start
PCArrayData[3] = ReadFloat afStream
--SampleRate
PCArrayData[4] = ReadFloat afStream
--Evaluations
PCArrayData[5] = ReadLong afStream
--End
PCArrayData[6] = (PCArrayData[3] + ((PCArrayData[5]-1) * PCArrayData[4]))
)
fClose afStream
PCArrayData
)
else #("--","--","--","--","--","--")
)