int CScriptBind_Physics::RegisterExplosionShape(IFunctionHandler *pH,const char *sGeometryFile,float fSize,int nIdMaterial,float fProbability,
																								const char *sSplintersFile, float fSplintersOffset, const char *sSplintersCloudEffect)
{
	//////////////////////////////////////////////////////////////////////////
	// Remove all this.
	//////////////////////////////////////////////////////////////////////////
	IStatObj *pObj = gEnv->p3DEngine->LoadStatObj( sGeometryFile,"#ForceBreakable",NULL,false );
	if (!pObj || pObj->IsDefaultObject())
	{
		ScriptWarning( "<RegisterExplosionShape> Object file %s not found",sGeometryFile );
		return pH->EndFunction();
	}
	pObj->AddRef();
	pObj->GetIndexedMesh(true); // prepare idxMesh now 

	if(sSplintersFile && *sSplintersFile!=0)			// if sSplintersFile was specified
	{
		IStatObj *pSplinters = gEnv->p3DEngine->LoadStatObj(sSplintersFile,NULL,NULL,false);
		if (pSplinters)
		{
			pObj->SetSubObjectCount(pObj->GetSubObjectCount()+1);
			IStatObj::SSubObject *pSubObj = pObj->GetSubObject(pObj->GetSubObjectCount()-1);
			pSubObj->nType = STATIC_SUB_OBJECT_MESH;
			pSubObj->bHidden = true;
			pSubObj->name = "splinters";
			(pSubObj->pStatObj = pSplinters)->AddRef();
			pSubObj->helperSize.x = fSplintersOffset;
			nIdMaterial |= 1<<16;

			if (*sSplintersCloudEffect)
			{
				pSplinters->SetSubObjectCount(pSplinters->GetSubObjectCount()+1);
				pSplinters->SetFlags(pSplinters->GetFlags() & ~STATIC_OBJECT_COMPOUND);
				pSubObj = pSplinters->GetSubObject(pSplinters->GetSubObjectCount()-1);
				pSubObj->nType = STATIC_SUB_OBJECT_DUMMY;
				pSubObj->bHidden = true;
				pSubObj->name = "splinters_cloud";
				pSubObj->properties = sSplintersCloudEffect;
			}
		}
	}

	phys_geometry *pPhysGeom = pObj->GetPhysGeom();
	if (pPhysGeom)
	{
		m_pPhysicalWorld->AddExplosionShape( pPhysGeom->pGeom,fSize,nIdMaterial,fProbability );
	}
	return pH->EndFunction();
}
Ejemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
// Name: ExtractPhysDataFromEvent
// Desc: Extracts collider's physical data from an event
// Note 1: Ideally *ALL* of this should be calculated offline and the minimal data loaded
// Note 2: We're currently duplicating some work done in CryAction, so should be reading that in
//--------------------------------------------------------------------------------------------------
bool CBreakableGlassSystem::ExtractPhysDataFromEvent(const EventPhysCollision& physEvent, SBreakableGlassPhysData& data, SBreakableGlassInitParams& initParams)
{
	if (IPhysicalEntity* pPhysEntity = physEvent.pEntity[PHYSEVENT_COLLIDEE])
	{
		// Get collider entity data
		const int entType = pPhysEntity->GetiForeignData();
		const int entPart = physEvent.partid[PHYSEVENT_COLLIDEE];

		// Local output data
		IStatObj* pStatObj = NULL;
		IMaterial* pRenderMat = NULL;
		phys_geometry* pPhysGeom = NULL;
		uint renderFlags = 0;

		Matrix34A entityMat;
		entityMat.SetIdentity();

		// Only handling simple objects at the moment
		const pe_type physType = pPhysEntity->GetType();

		if (physType == PE_STATIC || physType == PE_RIGID)
		{
			// Entity or static object?
			if (entType == PHYS_FOREIGN_ID_ENTITY)
			{
				IEntity* pEntity = (IEntity*)pPhysEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY);

				pStatObj = pEntity->GetStatObj(entPart);
				entityMat = pEntity->GetSlotWorldTM(entPart);

				if (IEntityRenderProxy* pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER))
				{
					pRenderMat = pRenderProxy->GetRenderMaterial(entPart);

					IRenderNode* pRenderNode = pRenderProxy->GetRenderNode();
					renderFlags = pRenderNode ? pRenderNode->GetRndFlags() : 0;

					// Fall back to top level material if sub-object fails to find it
					if (!pRenderMat)
					{
						pRenderMat = pRenderProxy->GetRenderMaterial();

						if (!pRenderMat && pStatObj)
						{
							pRenderMat = pStatObj->GetMaterial();
						}
					}
				}
			}
			else if (entType == PHYS_FOREIGN_ID_STATIC)
			{
				if (IRenderNode* pBrush = (IRenderNode*)physEvent.pForeignData[PHYSEVENT_COLLIDEE])
				{
					pStatObj = pBrush->GetEntityStatObj(0, 0, &entityMat);
					pRenderMat = pBrush->GetMaterial();
					renderFlags = pBrush->GetRndFlags();

					// May need to get sub-object and it's material
					if (pStatObj && pStatObj->GetFlags() & STATIC_OBJECT_COMPOUND)
					{
						if (IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(entPart))
						{
							pStatObj = pSubObj->pStatObj;

							if (!pSubObj->bIdentityMatrix)
							{
								entityMat = entityMat * pSubObj->tm;
							}

							// Find the correct sub-material
							// Note: We loop as the slots don't always line up
							const int subMtlCount = pRenderMat->GetSubMtlCount();
							for (int i = 0; i < subMtlCount; ++i)
							{
								if (IMaterial* pSubMat = pRenderMat->GetSubMtl(i))
								{
									if (pSubMat->GetSurfaceTypeId() == initParams.surfaceTypeId)
									{
										pRenderMat = pSubMat;
										break;
									}
								}
							}
						}
					}
				}
			}
		}

		// Validate geometry of collided object
		pPhysGeom = pStatObj ? pStatObj->GetPhysGeom() : NULL;
		IGeometry* pGeom = pPhysGeom ? pPhysGeom->pGeom : NULL;
		bool validGeom = false;

		primitives::box bbox;
		int thinAxis;

		if (pGeom)
		{
			// Determine thin geometry axis for glass alignment
			pGeom->GetBBox(&bbox);
			thinAxis = idxmin3((float*)&bbox.size);

			// Handle geometry mesh type
			switch (pGeom->GetType())
			{
			case GEOM_TRIMESH:
				// Perform full mesh analysis and extraction
				if (mesh_data* pPhysMeshData = (mesh_data*)pGeom->GetData())
				{
					if (ValidatePhysMesh(pPhysMeshData, thinAxis) && ExtractPhysMesh(pPhysMeshData, thinAxis, bbox, data.defaultFrag))
					{
						validGeom = true;
					}
				}
				break;

			case GEOM_BOX:
				// Simple box, so assume valid
				validGeom = true;
				break;

			default:
				// Only support boxes and tri-meshes
				break;
			}
		}

		// Invalid geometry, so can't continue
		if (!validGeom)
		{
			pPhysGeom = NULL;
		}

		// Attempt UV coord extraction from render mesh
		else
		{	
			ExtractUVCoords(pStatObj, bbox, thinAxis, data);
		}

		// Copy final data
		data.pStatObj = pStatObj;
		data.pPhysGeom = pPhysGeom;
		data.renderFlags = renderFlags;
		data.entityMat = entityMat;
		initParams.pGlassMaterial = pRenderMat;
	}

	return data.pStatObj && data.pPhysGeom && initParams.pGlassMaterial;
}//-------------------------------------------------------------------------------------------------