当前位置: 首页>>代码示例>>C++>>正文


C++ PxRigidDynamic::setActorFlag方法代码示例

本文整理汇总了C++中PxRigidDynamic::setActorFlag方法的典型用法代码示例。如果您正苦于以下问题:C++ PxRigidDynamic::setActorFlag方法的具体用法?C++ PxRigidDynamic::setActorFlag怎么用?C++ PxRigidDynamic::setActorFlag使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在PxRigidDynamic的用法示例。


在下文中一共展示了PxRigidDynamic::setActorFlag方法的6个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: AddShape

void PhysXPhysics::AddShape(Actor* pActor, PxGeometry* geometry, float density, const std::string& physicsMaterial, bool gravityEnabled, float linearDamping, float angularDamping, const std::string& bodyType)
{
	BE_ASSERT(pActor);
	ActorId actorId = pActor->GetId();
	BE_ASSERTf(m_actorRigidBodyMap.find(actorId) == m_actorRigidBodyMap.end(), "Actor with more than one rigidbody");

	Mat4x4 transform = Mat4x4::g_Identity;
	
	TransformComponent* pTransformComponent = pActor->GetComponent<TransformComponent>(TransformComponent::g_Name);

	if (pTransformComponent)
	{
		transform = pTransformComponent->GetTransform();
	}
	else 
	{
		//Doesnt work without transform
		BE_ERROR("Actor %s PhysicsComponent requires Shape to have Transform Component: %d", actorId);
		return;
	}

	PhysicsMaterialData material(LookupMaterialData(physicsMaterial));
	PxMaterial* mat = m_pPhysicsSdk->createMaterial(material.m_friction, material.m_friction, material.m_restitution);

	Vec3 translation, scale;
	Quaternion rotation;
	
	bool ok = transform.Decompose(translation, rotation, scale);
	PxQuat pxRot;
	PxVec3 pxLoc;
	Vec3ToPxVec(translation, &pxLoc);
	QuaternionToPxQuat(rotation, &pxRot);
	PxTransform t(pxLoc, pxRot);

	if (bodyType == "Dynamic")
	{
		PxRigidDynamic* body = PxCreateDynamic(*m_pPhysicsSdk, t, *geometry, *mat, density);
		body->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, !gravityEnabled);
		PxRigidBodyExt::updateMassAndInertia(*body, density);
		body->setLinearDamping(linearDamping);
		body->setAngularDamping(angularDamping);
		m_pScene->addActor(*body);

		m_actorRigidBodyMap[actorId] = body;
		m_rigidBodyActorMap[body] = actorId;
	}
	else
	{
		BE_ERROR("[Physics] BodyType not supported: %s", bodyType.c_str());
		return;
	}
}
开发者ID:jel-massih,项目名称:BombastEngine,代码行数:52,代码来源:PhysXPhysics.cpp

示例2: explode

void SampleSubmarine::explode(PxRigidActor* actor, const PxVec3& explosionPos, const PxReal explosionStrength)
{
	size_t numRenderActors = mRenderActors.size();
	for(PxU32 i = 0; i < numRenderActors; i++)
	{
		if(&(mRenderActors[i]->getPhysicsShape()->getActor()) == actor)
		{
			PxShape* shape = mRenderActors[i]->getPhysicsShape();
			PxTransform pose = PxShapeExt::getGlobalPose(*shape);
			
			PxGeometryHolder geom = shape->getGeometry();

			// create new actor from shape (to split compound)
			PxRigidDynamic* newActor = mPhysics->createRigidDynamic(pose);
			if(!newActor) fatalError("createRigidDynamic failed!");

			PxShape* newShape = newActor->createShape(geom.any(), *mMaterial);
			newShape->userData = mRenderActors[i];
			mRenderActors[i]->setPhysicsShape(newShape);
			
			newActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
			newActor->setLinearDamping(10.5f);
			newActor->setAngularDamping(0.5f);
			PxRigidBodyExt::updateMassAndInertia(*newActor, 1.0f);
			mScene->addActor(*newActor);
			mPhysicsActors.push_back(newActor);
			
			PxVec3 explosion = pose.p - explosionPos;
			PxReal len = explosion.normalize();
			explosion *= (explosionStrength / len);
			newActor->setLinearVelocity(explosion);
			newActor->setAngularVelocity(PxVec3(1,2,3));

		}
	}

	removeActor(actor);
}
开发者ID:thomhughes,项目名称:Awe,代码行数:38,代码来源:SampleSubmarine.cpp

示例3: cameraBase

void SampleParticles::Raygun::update(float dtime)
{
	if(!isEnabled())
		return;
	
	PX_ASSERT(mSample && mForceSmokeCapsule && mForceWaterCapsule && mRenderActor);

	// access properties from sample
	PxScene& scene = mSample->getActiveScene();
	PxVec3 position = mSample->getCamera().getPos();
	PxTransform cameraPose = mSample->getCamera().getViewMatrix();
	PxMat33 cameraBase(cameraPose.q);
	PxVec3 cameraForward = -cameraBase[2];
	PxVec3 cameraUp = -cameraBase[1];
	
	// perform raycast here and update impact point
	PxRaycastHit hit;
	mIsImpacting = scene.raycastSingle(cameraPose.p, cameraForward, 500.0f, PxSceneQueryFlags(0xffffffff), hit);
	float impactParam = mIsImpacting ? (hit.impact - position).magnitude() : FLT_MAX;	

	PxTransform rayPose(position + cameraUp * 0.5f, cameraPose.q*PxQuat(PxHalfPi, PxVec3(0,1,0)));

	updateRayCapsule(mForceSmokeCapsule, rayPose, 1.0f);
	updateRayCapsule(mForceWaterCapsule, rayPose, 0.3f);
	mRenderActor->setTransform(rayPose);

	// if we had an impact
	if (impactParam < FLT_MAX)
	{
		PxVec3 impactPos = position + cameraForward*impactParam;
		// update emitter with new impact point and direction
		if(mSmokeEmitter.emitter)
			mSmokeEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));
		if(mDebrisEmitter.emitter)
			mDebrisEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));

		// spawn new RB debris
		if(mRbDebrisTimer < 0.0f && impactParam < FLT_MAX) 
		{
			mRbDebrisTimer = RAYGUN_RB_DEBRIS_RATE;

			PxVec3 randDir(getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f));
			PxVec3 vel = -7.0f * (cameraForward + RAYGUN_RB_DEBRIS_ANGLE_RANDOMNESS * randDir.getNormalized());
			PxVec3 dim(getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE));
			// give spawn position, initial velocity and dimensions, spawn convex
			// which will not act in scene queries
			PxConvexMesh* convexMesh = generateConvex(mSample->getPhysics(), mSample->getCooking(), RAYGUN_RB_DEBRIS_SCALE);
			mSample->runtimeAssert(convexMesh, "Error generating convex for debris.\n");
			PxRigidDynamic* debrisActor = PxCreateDynamic(
				mSample->getPhysics(), 
				PxTransform(impactPos - cameraForward * 0.5f), 
				PxConvexMeshGeometry(convexMesh), 
				mSample->getDefaultMaterial(), 1.f);  
			mSample->getActiveScene().addActor(*debrisActor);

			PX_ASSERT(debrisActor->getNbShapes() == 1);
			PxShape* debrisShape;
			debrisActor->getShapes(&debrisShape, 1);
			debrisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
			debrisActor->setLinearVelocity(vel);
			debrisActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
			debrisActor->setAngularDamping(0.5f);
			
			// default material is green for debris
			RenderMaterial* debriMaterial = mSample->getMaterial(MATERIAL_HEIGHTFIELD);
			if(!debriMaterial) 
			{
				debriMaterial = mSample->mRenderMaterials[MATERIAL_GREEN];				
			}
			mSample->createRenderObjectsFromActor(debrisActor, debriMaterial);
			mDebrisLifetime[debrisShape] = RAYGUN_RB_DEBRIS_LIFETIME;
		}
	}

	// update debris lifetime, remove if life ends
	DebrisLifetimeMap::iterator it = mDebrisLifetime.begin();
	while(it != mDebrisLifetime.end()) 
	{
		(*it).second -= dtime;
		if((*it).second < 0.0f) 
		{
			PxShape* debrisShape = (*it).first;
			PX_ASSERT(debrisShape);

			// remove convex mesh
			PxConvexMeshGeometry geometry;
			bool isConvex = debrisShape->getConvexMeshGeometry(geometry);
			PX_ASSERT(isConvex);
			PX_UNUSED(isConvex);
			geometry.convexMesh->release();
			
			// remove render and physics actor
			PxRigidActor& actorToRemove = debrisShape->getActor();
			mSample->removeActor(&actorToRemove);			
			actorToRemove.release();
			
//.........这里部分代码省略.........
开发者ID:akurt5,项目名称:AIEShit,代码行数:101,代码来源:SampleParticles.cpp

示例4: onTickPreRender

void SampleSubmarine::onTickPreRender(float dtime)
{
	// handle mine (and submarine) explosion
	if(mSubmarineActor)
	{
		// explode all touched mines, apply damage and force to submarine
		PxVec3 subMarinePos = mSubmarineActor->getGlobalPose().p;
		const size_t nbExplodeSeamines = mMinesToExplode.size();
		for(PxU32 i=0; i < nbExplodeSeamines; i++)
		{
			Seamine* mine = mMinesToExplode[i];
			PxVec3 explosionPos = mine->mMineHead->getGlobalPose().p;
			
			// disable contact trigger callback of the chain & enable gravity
			const size_t nbLinks = mine->mLinks.size();
			for(PxU32 j = 0; j < nbLinks; j++)
			{
				PxRigidDynamic* link = mine->mLinks[j];
				setupFiltering(link, 0, 0);
				link->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, false);
			}
			
			// remove mine head
			std::vector<Seamine*>::iterator mineIter = std::find(mSeamines.begin(), mSeamines.end(), mine);
			if(mineIter != mSeamines.end())
				mSeamines.erase(mineIter);
			removeActor(mine->mMineHead);
			delete mine;

			// give damage to submarine
			static const PxReal strength = 400.0f;
			PxVec3 explosion = subMarinePos - explosionPos;
			PxReal len = explosion.normalize();
			PxReal damage = strength * (1.0f/len);
			explosion *= damage;
			mSubmarineActor->addForce(explosion*300);
			gSubmarineHealth = PxMax(gSubmarineHealth-PxI32(damage), 0);
			if(gSubmarineHealth == 0)
			{
				mSubmarineCameraController->init(subMarinePos - getCamera().getViewDir()*10.0f, getCamera().getRot());
				explode(mSubmarineActor, subMarinePos /*- explosion*0.2f*/, damage);
				mCameraAttachedToActor = NULL;
				mSubmarineCameraController->setFollowingMode(false);
				mSubmarineActor = NULL;
				break;
			}
		}
		mMinesToExplode.clear();
	}

	// respawn Crabs
	const size_t nbCrabs = mCrabs.size();
	for(PxU32 i = 0; i < nbCrabs; i++)
	{
		Crab* crab = mCrabs[i];
		if(crab->needsRespawn())
		{
			PxRigidDynamic* prevBody = crab->getCrabBody();
			PxVec3 prevPos = prevBody->getGlobalPose().p;
			delete crab;
			mCrabs[i] = SAMPLE_NEW(Crab)(*this, prevPos, mManagedMaterials[MATERIAL_RED]);
			if(gCrab == crab)
				gCrab = mCrabs[i];
			if(mCameraAttachedToActor == prevBody)
				mCameraAttachedToActor = mCrabs[i]->getCrabBody();
		}
	}

	// update camera
	if(mCameraAttachedToActor)
		mSubmarineCameraController->updateFollowingMode(getCamera(), dtime, mCameraAttachedToActor->getGlobalPose().p);

	// start the simulation
	PhysXSample::onTickPreRender(dtime);
}
开发者ID:thomhughes,项目名称:Awe,代码行数:75,代码来源:SampleSubmarine.cpp

示例5: createSeamine

Seamine* SampleSubmarine::createSeamine(const PxVec3& inPosition, PxReal inHeight)
{
	static const PxReal chainLinkLength = 2.0f;
	static const PxReal linkSpacing = 0.05f;
	static const PxReal mineHeadRadius = 1.5f;
	const PxVec3 mineStartPos = inPosition;
	static const PxVec3 linkOffset = PxVec3(0, chainLinkLength + linkSpacing, 0);
	static const PxVec3 halfLinkOffset = linkOffset * 0.5f;
	static const PxVec3 linkDim = PxVec3(chainLinkLength*0.125f, chainLinkLength*0.5f, chainLinkLength*0.125f);
	PxU32 numLinks = PxU32((inHeight - 2.0f*mineHeadRadius) / (chainLinkLength + linkSpacing));
	numLinks = numLinks ? numLinks : 1;

	Seamine* seamine = SAMPLE_NEW(Seamine);
	mSeamines.push_back(seamine);

	// create links from floor
	PxVec3 linkPos = mineStartPos + halfLinkOffset;
	PxRigidActor* prevActor = NULL;
	for(PxU32 i = 0; i < numLinks; i++)
	{
		// create the link actor
		PxRigidDynamic* link = createBox(linkPos, linkDim, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>();
		if(!link) fatalError("createBox failed!");
		// back reference to mineHead
		link->userData = seamine;
		seamine->mLinks.push_back(link);

		setupFiltering(link, FilterGroup::eMINE_LINK, FilterGroup::eSUBMARINE);
		link->setLinearDamping(0.5f);
		link->setAngularDamping(0.5f);
		link->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);

		// create distance joint between link and prevActor
		PxTransform linkFrameA = prevActor ? PxTransform(halfLinkOffset, PxQuat::createIdentity()) : PxTransform(mineStartPos, PxQuat::createIdentity());
		PxTransform linkFrameB = PxTransform(-halfLinkOffset, PxQuat::createIdentity());
		PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, link, linkFrameB);
		if(!joint) fatalError("PxDistanceJointCreate failed!");

		// set min & max distance to 0
		joint->setMaxDistance(0.0f);
		joint->setMinDistance(0.0f);
		// setup damping & spring
		joint->setDamping(1.0f * link->getMass());
		joint->setSpring(400.0f * link->getMass());
		joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);

		// add to joints array for cleanup
		mJoints.push_back(joint);

		prevActor = link;
		linkPos += linkOffset;
	}

	// create mine head
	linkPos.y += mineHeadRadius - (chainLinkLength*0.5f);
	PxRigidDynamic* mineHead = createSphere(linkPos, mineHeadRadius, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>();
	mineHead->userData = seamine;
	seamine->mMineHead = mineHead;
	
	mineHead->setLinearDamping(0.5f);
	mineHead->setAngularDamping(0.5f);
	mineHead->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
	
	// setup filtering to trigger contact reports when submarine touches the minehead
	setupFiltering(mineHead, FilterGroup::eMINE_HEAD, FilterGroup::eSUBMARINE);


	// create distance joint between mine head and prevActor
	PxTransform linkFrameA = PxTransform(halfLinkOffset, PxQuat::createIdentity());
	PxTransform linkFrameB = PxTransform(PxVec3(0, -mineHeadRadius - linkSpacing*0.5f, 0), PxQuat::createIdentity());
	PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, mineHead, linkFrameB);
	if(!joint) fatalError("PxDistanceJointCreate failed!");

	// set min & max distance to 0
	joint->setMaxDistance(0.0f);
	joint->setMinDistance(0.0f);
	// setup damping & spring
	joint->setDamping(1.0f * mineHead->getMass());
	joint->setSpring(400.0f * mineHead->getMass());
	joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);

	// add to joints array for cleanup
	mJoints.push_back(joint);

	return seamine;
}
开发者ID:thomhughes,项目名称:Awe,代码行数:86,代码来源:SampleSubmarine.cpp

示例6: CreatePhysicsState


//.........这里部分代码省略.........
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word0", PSimFilterData.word0 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word1", PSimFilterData.word1 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word2", PSimFilterData.word2 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word3", PSimFilterData.word3 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word0", PQueryFilterData.word0 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word1", PQueryFilterData.word1 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word2", PQueryFilterData.word2 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word3", PQueryFilterData.word3 ) );

	// Set the PhysX material in the shape descriptor
	PxMaterial* PMaterial = PhysMat->GetPhysXMaterial();
	verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.material", (physx::PxU64)PMaterial) );

	// Set the rest depth to match the skin width in the shape descriptor
	const physx::PxCookingParams& CookingParams = GApexSDK->getCookingInterface()->getParams();
	verify( NxParameterized::setParamF32(*ActorParams,"p3ShapeDescTemplate.restOffset", -CookingParams.skinWidth) );

	// Set the PhysX material in the actor descriptor
	verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eDISABLE_GRAVITY",false) );
	verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eVISUALIZATION",true) );

	// Set the PxActor's and PxShape's userData fields to this component's body instance
	verify( NxParameterized::setParamU64(*ActorParams,"p3ActorDescTemplate.userData", 0 ) );

	// All shapes created by this DestructibleActor will have the userdata of the owning component.
	// We need this, as in some cases APEX is moving shapes accross actors ( ex. FormExtended structures )
	verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.userData", (PxU64)&PhysxUserData ) );

	// Set up the body desc template in the actor descriptor
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.angularDamping", BodyInstance.AngularDamping ) );
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.linearDamping", BodyInstance.LinearDamping ) );
	const PxTolerancesScale& PScale = GPhysXSDK->getTolerancesScale();
	PxF32 SleepEnergyThreshold = 0.00005f*PScale.speed*PScale.speed;	// 1/1000 Default, since the speed scale is quite high
	if (BodyInstance.SleepFamily == ESleepFamily::Sensitive)
	{
		SleepEnergyThreshold /= 20.0f;
	}
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.sleepThreshold", SleepEnergyThreshold) );
//	NxParameterized::setParamF32(*ActorParams,"bodyDescTemplate.sleepDamping", SleepDamping );
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.density", 0.001f*PhysMat->Density) );	// Convert from g/cm^3 to kg/cm^3
	// Enable CCD if requested
	verify( NxParameterized::setParamBool(*ActorParams,"p3BodyDescTemplate.flags.eENABLE_CCD", BodyInstance.bUseCCD != 0) );
	// Ask the actor to create chunk events, for more efficient visibility updates
	verify( NxParameterized::setParamBool(*ActorParams,"createChunkEvents", true) );

	// Enable hard sleeping if requested
	verify( NxParameterized::setParamBool(*ActorParams,"useHardSleeping", bEnableHardSleeping) );

	

	// Destructibles are always dynamic or kinematic, and therefore only go into one of the scenes
	const uint32 SceneType = BodyInstance.UseAsyncScene(PhysScene) ? PST_Async : PST_Sync;
	NxApexScene* ApexScene = PhysScene->GetApexScene(SceneType);
	PxScene* PScene = PhysScene->GetPhysXScene(SceneType);

	BodyInstance.SceneIndexSync = SceneType == PST_Sync ? PhysScene->PhysXSceneIndex[PST_Sync] : 0;
	BodyInstance.SceneIndexAsync = SceneType == PST_Async ? PhysScene->PhysXSceneIndex[PST_Async] : 0;
	check(ApexScene);

	ChunkInfos.Reset(ChunkCount);
	ChunkInfos.AddZeroed(ChunkCount);
	PhysxChunkUserData.Reset(ChunkCount);
	PhysxChunkUserData.AddZeroed(ChunkCount);

	// Create an APEX NxDestructibleActor from the Destructible asset and actor descriptor
	ApexDestructibleActor = static_cast<NxDestructibleActor*>(TheDestructibleMesh->ApexDestructibleAsset->createApexActor(*ActorParams, *ApexScene));
	check(ApexDestructibleActor);

	// Make a backpointer to this component
	PhysxUserData = FPhysxUserData(this);
	ApexDestructibleActor->userData = &PhysxUserData;

	// Cache cooked collision data
	// BRGTODO : cook in asset
	ApexDestructibleActor->cacheModuleData();

	// BRGTODO : Per-actor LOD setting
//	ApexDestructibleActor->forcePhysicalLod( DestructibleActor->LOD );

	// Start asleep if requested
	PxRigidDynamic* PRootActor = ApexDestructibleActor->getChunkPhysXActor(0);


	//  Put to sleep or wake up only if the component is physics-simulated
	if (PRootActor != NULL && BodyInstance.bSimulatePhysics)
	{
		SCOPED_SCENE_WRITE_LOCK(PScene);	//Question, since apex is defer adding actors do we need to lock? Locking the async scene is expensive!

		PRootActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, !BodyInstance.bEnableGravity);

		// Sleep/wake up as appropriate
		if (!BodyInstance.bStartAwake)
		{
			ApexDestructibleActor->setChunkPhysXActorAwakeState(0, false);
		}
		}

	UpdateBounds();
#endif	// #if WITH_APEX
}
开发者ID:johndpope,项目名称:UE4,代码行数:101,代码来源:DestructibleComponent.cpp


注:本文中的PxRigidDynamic::setActorFlag方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。