예제 #1
0
void PxCollectionExt::releaseObjects(PxCollection& collection, bool releaseExclusiveShapes)
{
	shdfnd::Array<PxBase*> releasableObjects;

	for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
	{	
		PxBase* s = &collection.getObject(i);
		// pruning structure must be released before its actors
		if(s->is<PxPruningStructure>())
		{
			if(!releasableObjects.empty())
			{
				PxBase* first = releasableObjects[0];
				releasableObjects.pushBack(first);
				releasableObjects[0] = s;
			}
		}
		else
		{
			if (s->isReleasable() && (releaseExclusiveShapes || !s->is<PxShape>() || !s->is<PxShape>()->isExclusive()))
				releasableObjects.pushBack(s);
		}
	}

	for (PxU32 i = 0; i < releasableObjects.size(); ++i)
		releasableObjects[i]->release();		

	while (collection.getNbObjects() > 0)
		collection.remove(collection.getObject(0));
}
예제 #2
0
void PxCollectionExt::releaseObjects(PxCollection& collection)
{
	shdfnd::Array<PxBase*> releasableObjects;

	for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
	{	
		PxBase* s = &collection.getObject(i);
		if(s->isReleasable())
			releasableObjects.pushBack(s);
	}

	for (PxU32 i = 0; i < releasableObjects.size(); ++i)
		releasableObjects[i]->release();		

	while (collection.getNbObjects() > 0)
		collection.remove(collection.getObject(0));
}
void SerializationContext::registerReference(PxBase& serializable, PxU32 kind, size_t reference)
{
#if PX_CHECKED
	if ((kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) == 0 && reference > 0xffffffff)
	{
		Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerializationContext::registerReference: only 32 bit indices supported.");
		return;
	}
#endif

	bool isExternal = mExternalRefs && mExternalRefs->contains(serializable);
	PxU32 index;
	if (isExternal)
	{
		PxSerialObjectId id = mExternalRefs->getId(serializable);
		PX_ASSERT(id != PX_SERIAL_OBJECT_ID_INVALID);
		if (const Ps::HashMap<PxSerialObjectId, PxU32>::Entry* entry = mImportReferencesMap.find(id))
		{
			index = entry->second;
		}
		else
		{
			index = mImportReferences.size();
			mImportReferencesMap.insert(id, index);
			mImportReferences.pushBack(ImportReference(id, serializable.getConcreteType()));
		}
	}
	else
	{
		PX_ASSERT(mCollection.contains(serializable));
		index = mObjToCollectionIndexMap[&serializable];
	}

	InternalRefMap& targetMap = (kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) ? mInternalReferencesPtrMap : mInternalReferencesIdxMap;
	targetMap[InternalRefKey(reference, kind)] = SerialObjectIndex(index, isExternal);
}
bool PxSerialization::serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& pxCollection, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs, bool exportNames)
{
	if(!PxSerialization::isSerializable(pxCollection, sr, pxExternalRefs))
		return false; 
		
	Cm::Collection& collection = static_cast<Cm::Collection&>(pxCollection);
	const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs);
	
	//temporary memory stream which allows fixing up data up stream
	
	SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
	
	// sort collection by "order" value (this will be the order in which they get serialized)
	sortCollection(collection, sn, false);

	//initialized the context with the sorted collection. 
	SerializationContext context(collection, externalRefs);
	
	// gather reference information
    bool hasDeserializedAssets = false;
	{
		const PxU32 nb = collection.internalGetNbObjects();
		for(PxU32 i=0;i<nb;i++)
		{
			PxBase* s = collection.internalGetObject(i);
			PX_ASSERT(s && s->getConcreteType());
#ifdef PX_CHECKED
			//can't guarantee marked padding for deserialized instances
			if(!(s->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY))
			   hasDeserializedAssets = true;
#endif
			const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
			PX_ASSERT(serializer);
			serializer->registerReferences(*s, context);
		}
	}

	// now start the actual serialization into the output stream
	OutputStreamWriter writer(outputStream);
	LegacySerialStream stream(writer, collection, exportNames);
	
	writeHeader(stream, hasDeserializedAssets);

	// write size of collection
	stream.alignData(PX_SERIAL_ALIGN);
	PxU32 nbObjectsInCollection = collection.internalGetNbObjects();
	stream.writeData(&nbObjectsInCollection, sizeof(PxU32));

	// write the manifest table (PxU32 offset, PxConcreteType type)
	{
		Ps::Array<ManifestEntry> manifestTable(collection.internalGetNbObjects());
		PxU32 headerOffset = 0;
		for(PxU32 i=0;i<collection.internalGetNbObjects();i++)
		{
			PxBase* s = collection.internalGetObject(i);
			PX_ASSERT(s && s->getConcreteType());
			PxType concreteType = s->getConcreteType();
			const PxSerializer* serializer = sn.getSerializer(concreteType);
			PX_ASSERT(serializer);
			manifestTable[i] = ManifestEntry(headerOffset, concreteType);
			PxU32 classSize = PxU32(serializer->getClassSize());
			headerOffset += Cm::getPadding(classSize, PX_SERIAL_ALIGN) + classSize;
		}
		stream.alignData(PX_SERIAL_ALIGN);
		const PxU32 nb = manifestTable.size();
		stream.writeData(&nb, sizeof(PxU32));
		stream.writeData(manifestTable.begin(), manifestTable.size()*sizeof(ManifestEntry));
			
		//store offset for end of object buffer (PxU32 offset)
		stream.writeData(&headerOffset, sizeof(PxU32));
	}

	// write import references
	{
		const Ps::Array<ImportReference>& importReferences = context.getImportReferences();
		stream.alignData(PX_SERIAL_ALIGN);
		const PxU32 nb = importReferences.size();
		stream.writeData(&nb, sizeof(PxU32));
		stream.writeData(importReferences.begin(), importReferences.size()*sizeof(ImportReference));
	}

	// write export references
	{
		PxU32 nbIds = collection.getNbIds();
		Ps::Array<ExportReference> exportReferences(nbIds);
		//we can't get quickly from id to object index in collection. 
		//if we only need this here, its not worth to build a hash
		nbIds = 0;
		for (PxU32 i=0;i<collection.getNbObjects();i++)
		{
			PxBase& obj = collection.getObject(i);
			PxSerialObjectId id = collection.getId(obj);
			if (id != PX_SERIAL_OBJECT_ID_INVALID)
			{
				SerialObjectIndex objIndex(i, false); //i corresponds to manifest entry
				exportReferences[nbIds++] = ExportReference(id, objIndex);
			}
		}
		stream.alignData(PX_SERIAL_ALIGN);
		stream.writeData(&nbIds, sizeof(PxU32));
		stream.writeData(exportReferences.begin(), exportReferences.size()*sizeof(ExportReference));
	}

	// write internal references
	{
		InternalRefMap& internalReferencesPtrMap = context.getInternalReferencesPtrMap();
		Ps::Array<InternalReferencePtr> internalReferencesPtr(internalReferencesPtrMap.size());
		PxU32 nbInternalPtrReferences = 0;
		for(InternalRefMap::Iterator iter = internalReferencesPtrMap.getIterator(); !iter.done(); ++iter)
			internalReferencesPtr[nbInternalPtrReferences++] = InternalReferencePtr(iter->first.first, iter->first.second, iter->second);

		InternalRefMap& internalReferencesIdxMap = context.getInternalReferencesIdxMap();
		Ps::Array<InternalReferenceIdx> internalReferencesIdx(internalReferencesIdxMap.size());
		PxU32 nbInternalIdxReferences = 0;
		for(InternalRefMap::Iterator iter = internalReferencesIdxMap.getIterator(); !iter.done(); ++iter)
			internalReferencesIdx[nbInternalIdxReferences++] = InternalReferenceIdx(Ps::to32(iter->first.first), iter->first.second, iter->second);

		stream.alignData(PX_SERIAL_ALIGN);
		
		stream.writeData(&nbInternalPtrReferences, sizeof(PxU32));
		stream.writeData(internalReferencesPtr.begin(), internalReferencesPtr.size()*sizeof(InternalReferencePtr));

		stream.writeData(&nbInternalIdxReferences, sizeof(PxU32));
		stream.writeData(internalReferencesIdx.begin(), internalReferencesIdx.size()*sizeof(InternalReferenceIdx));
	}

	// write object data
	{
		stream.alignData(PX_SERIAL_ALIGN);
		const PxU32 nb = collection.internalGetNbObjects();
		for(PxU32 i=0;i<nb;i++)
		{
			PxBase* s = collection.internalGetObject(i);
			PX_ASSERT(s && s->getConcreteType());
			const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
			PX_ASSERT(serializer);
			stream.alignData(PX_SERIAL_ALIGN);
			serializer->exportData(*s, stream);
		}
	}

	// write extra data
	{
		const PxU32 nb = collection.internalGetNbObjects();
		for(PxU32 i=0;i<nb;i++)
		{
			PxBase* s = collection.internalGetObject(i);
			PX_ASSERT(s && s->getConcreteType());

			const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
			PX_ASSERT(serializer);

			stream.alignData(PX_SERIAL_ALIGN);
			serializer->exportExtraData(*s, stream);
		}
	}

	return true;
}
예제 #5
0
PxCollection* PxSerialization::createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs)
{
#ifdef PX_CHECKED
	if(size_t(memBlock) & (PX_SERIAL_FILE_ALIGN-1))
	{
		Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Buffer must be 128-bytes aligned.");
		return NULL;
	}
#endif
	PxU8* address = reinterpret_cast<PxU8*>(memBlock);
	const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs);
			
	PxU32 version;
	if (!readHeader(address, version))
	{
		return NULL;
	}

	ManifestEntry* manifestTable;
	PxU32 nbObjectsInCollection;
	PxU32 objectDataEndOffset;

	// read number of objects in collection
	address = Cm::alignPtr(address);
	nbObjectsInCollection = read32(address);

	// read manifest (PxU32 offset, PxConcreteType type)
	{
		address = Cm::alignPtr(address);
		PxU32 nbManifestEntries = read32(address);
		PX_ASSERT(*reinterpret_cast<PxU32*>(address) == 0); //first offset is always 0
		manifestTable = (nbManifestEntries > 0) ? reinterpret_cast<ManifestEntry*>(address) : NULL;
		address += nbManifestEntries*sizeof(ManifestEntry);
		objectDataEndOffset = read32(address);
	}

	ImportReference* importReferences;
	PxU32 nbImportReferences;
	// read import references
	{
		address = Cm::alignPtr(address);
		nbImportReferences = read32(address);
		importReferences = (nbImportReferences > 0) ? reinterpret_cast<ImportReference*>(address) : NULL;
		address += nbImportReferences*sizeof(ImportReference);
	}

	if (!checkImportReferences(importReferences, nbImportReferences, externalRefs))
	{
		return NULL;
	}

	ExportReference* exportReferences;
	PxU32 nbExportReferences;
	// read export references
	{
		address = Cm::alignPtr(address);
		nbExportReferences = read32(address);
		exportReferences = (nbExportReferences > 0) ? reinterpret_cast<ExportReference*>(address) : NULL;
		address += nbExportReferences*sizeof(ExportReference);
	}

	// read internal references arrays
	PxU32 nbInternalPtrReferences = 0;
	PxU32 nbInternalIdxReferences = 0;
	InternalReferencePtr* internalPtrReferences = NULL;
	InternalReferenceIdx* internalIdxReferences = NULL;
	{
		address = Cm::alignPtr(address);

		nbInternalPtrReferences = read32(address);
		internalPtrReferences = (nbInternalPtrReferences > 0) ? reinterpret_cast<InternalReferencePtr*>(address) : NULL;
		address += nbInternalPtrReferences*sizeof(InternalReferencePtr);

		nbInternalIdxReferences = read32(address);
		internalIdxReferences = (nbInternalIdxReferences > 0) ? reinterpret_cast<InternalReferenceIdx*>(address) : NULL;
		address += nbInternalIdxReferences*sizeof(InternalReferenceIdx);
	}

	// create internal references map
	PxF32 loadFactor = 0.75f;
	PxF32 _loadFactor = 1.0f / loadFactor;
	PxU32 hashSize = PxU32((nbInternalPtrReferences + nbInternalIdxReferences + 1)*_loadFactor);
	InternalRefMap internalReferencesMap(hashSize, loadFactor);
	{
		//create hash (we should load the hashes directly from memory)
		for (PxU32 i=0;i<nbInternalPtrReferences;i++)
		{
			const InternalReferencePtr& ref = internalPtrReferences[i];
			internalReferencesMap.insertUnique( InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex));
		}
		for (PxU32 i=0;i<nbInternalIdxReferences;i++)
		{
			const InternalReferenceIdx& ref = internalIdxReferences[i];
			internalReferencesMap.insertUnique(InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex));
		}
	}

	SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
	Cm::Collection* collection = static_cast<Cm::Collection*>(PxCreateCollection());
	PX_ASSERT(collection);
	collection->mObjects.reserve((PxU32)(nbObjectsInCollection*_loadFactor) + 1);
	if(nbExportReferences > 0)
	    collection->mIds.reserve((PxU32)(nbExportReferences*_loadFactor) + 1);

	PxU8* addressObjectData = Cm::alignPtr(address);
	PxU8* addressExtraData = Cm::alignPtr(addressObjectData + objectDataEndOffset);

	DeserializationContext context(manifestTable, importReferences, addressObjectData, internalReferencesMap, externalRefs, addressExtraData, version);
	
	// iterate over memory containing PxBase objects, create the instances, resolve the addresses, import the external data, add to collection.
	{
		PxU32 nbObjects = nbObjectsInCollection;

		while(nbObjects--)
		{
			address = Cm::alignPtr(address);
			context.alignExtraData();

			// read PxBase header with type and get corresponding serializer.
			PxBase* header = reinterpret_cast<PxBase*>(address);
			const PxType classType = header->getConcreteType();
			const PxSerializer* serializer = sn.getSerializer(classType);
			PX_ASSERT(serializer);

			PxBase* instance = serializer->createObject(address, context);
			if (!instance)
			{
				Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, 
					"Cannot create class instance for concrete type %d.", classType);
				collection->release();
				return NULL;
			}

			collection->internalAdd(instance);
		}
	}

	PX_ASSERT(nbObjectsInCollection == collection->internalGetNbObjects());
	
	// update new collection with export references
	{
		PX_ASSERT(addressObjectData != NULL);
		for (PxU32 i=0;i<nbExportReferences;i++)
		{
			bool isExternal;
			PxU32 manifestIndex = exportReferences[i].objIndex.getIndex(isExternal);
			PX_ASSERT(!isExternal);
			PxBase* obj = reinterpret_cast<PxBase*>(addressObjectData + manifestTable[manifestIndex].offset);
			collection->mIds.insertUnique(exportReferences[i].id, obj);
			collection->mObjects[obj] = exportReferences[i].id;
		}
	}

	PxAddCollectionToPhysics(*collection);
	return collection;
}