예제 #1
0
//called every frame.  Here we set up the target paramters so that they
//can be used by each node passed into the perform function.
void FormationBhvr::InitAtThisTime(TimeValue t)
{

	INode *leaderNode = GetLeader(t);
	if(leaderNode)
	{
	
		if(prevPosTime==TIME_NegInfinity||prevPosTime != t - GetTicksPerFrame())
		{
			//get the right leaderPrevPos.
			leaderPrevPos = GetCurrentMatrix(leaderNode,t-GetTicksPerFrame()).GetTrans();

		}
		leaderPos = GetCurrentMatrix(leaderNode,t).GetTrans();
		leaderVel = leaderPos - leaderPrevPos;//use the preivous position to get the velocity.

		leaderSpeed = leaderVel.FLength();
		//normalize the velocity.
		if(leaderSpeed!=0.0f)
			leaderVel /= leaderSpeed;
		else
		{
			leaderVel.x = leaderVel.y = leaderVel.z = 0.0f;
		}
		//set up the previous for the next time.
		leaderPrevPos = leaderPos;
		prevPosTime = t;
	}
}
예제 #2
0
//This will set the formation
void FormationBhvr::SetFormation(TimeValue t)
{
	INode *node;
	Matrix3 tempMatrix;


	//Make sure that the leader is not part of the follower array..
	RemoveLeaderFromFormation(t);


	INode *leader =  GetLeader(t);

	if(leader==NULL)
		return;
	Matrix3 leaderPosition = GetCurrentMatrix(leader,t);
	leaderPosition.NoScale(); //kill any scale if we have it 
	leaderPosition.Invert();  //it's inverted...


	int numDelegates = GetFollowerCount(t);	

	//zero out the formation matrix that's used for saving it out.
	pblock->ZeroCount(follower_matrix1);
	pblock->ZeroCount(follower_matrix2);
	pblock->ZeroCount(follower_matrix3);
	pblock->ZeroCount(follower_matrix4);

	for(int i =0;i<numDelegates;i++)
	{

		node = GetFollower(t,i);
		if(node)
		{
			tempMatrix = GetCurrentMatrix(node,t);
			tempMatrix.NoScale();
			Matrix3 leaderMat =tempMatrix*leaderPosition;
			AppendFollowerMatrix(t,leaderMat);

			//killed because matrix3 wasn't working ...pblock->Append(follower_matrix,1,&leaderMat);
		 
		
		}
		else
		{
			//we still set up follower_matrix so that the counts
			//of the follower_matrix tab and the follower tab are equal.
			tempMatrix.IdentityMatrix();
			AppendFollowerMatrix(t,tempMatrix);

			//pblock->Append(follower_matrix,1,&tempMat);
	
		}
	}

}
예제 #3
0
	NewtonBody* CreateRigidBody(DemoEntityManager* const scene, dFloat mass, NewtonCollision* const deformableCollision)
	{
		//create the rigid body
		NewtonWorld* const world = scene->GetNewton();
		dMatrix matrix(GetCurrentMatrix());

		//matrix.m_posit.m_y = FindFloor (world, matrix.m_posit.m_x, matrix.m_posit.m_z) + 4.0f;
		SetMatrix(*scene, dQuaternion(), matrix.m_posit);
		SetMatrix(*scene, dQuaternion(), matrix.m_posit);
		NewtonBody* const deformableBody = NewtonCreateDynamicBody(world, deformableCollision, &matrix[0][0]);

		// set the mass matrix
		NewtonBodySetMassProperties(deformableBody, mass, deformableCollision);

		// save the pointer to the graphic object with the body.
		NewtonBodySetUserData(deformableBody, this);

		// assign the wood id
		//	NewtonBodySetMaterialGroupID (deformableBody, materialId);

		// set a destructor for this rigid body
		NewtonBodySetDestructorCallback(deformableBody, PhysicsBodyDestructor);

		// set the transform call back function
		NewtonBodySetTransformCallback(deformableBody, DemoEntity::TransformCallback);

		// set the force and torque call back function
		NewtonBodySetForceAndTorqueCallback(deformableBody, PhysicsApplyGravityForce);

		return deformableBody;
	}
예제 #4
0
//Get a bounding box.  This is used for when we display the formation continously.
void FormationBhvr::GetWorldBoundBox(TimeValue t, ViewExp *vpt, Box3& box)
{
	if ( ! vpt || ! vpt->IsAlive() )
	{
		box.Init();
		return;
	}

	//make sure we have everything we need...
	if(DisplayFormation(t)==FALSE) return;
	if(GetFollowerCount(t)<=0) return;
	if(GetFollowerMatrixCount(t)<=0) return; //possible to not have this set when the follower is set..

	INode *leaderNode;
	leaderNode = GetLeader(t);
	if(leaderNode==NULL) return;



	//for each follower we need to increase the bounding box by it's
	//world position location...
	for(int i =0;i<GetFollowerCount(t);i++)
	{
		if(GetFollower(t,i)) //if we have a a node...
		{
			Matrix3 worldSpace = GetFollowerMatrix(t,i)*GetCurrentMatrix(leaderNode,t);
			Point3 trans(worldSpace.GetTrans());
			//expand the box by the worldposition...
			box += trans;
		}
	}
}
예제 #5
0
파일: formation.cpp 프로젝트: 2asoft/xray
//The display function that is used to display the formation.
int FormationBhvr::Display(TimeValue t, ViewExp *vpt) 
{
    // setup

	int i,j;
   	
	if(DisplayFormation(t)==FALSE) return FALSE;

	if(GetFollowerCount(t)<=0) return FALSE;
	if(GetFollowerMatrixCount(t)<=0) return FALSE;

	INode *leaderNode;
	leaderNode = GetLeader(t);
	if(leaderNode==NULL) return FALSE;
	
	
	//check tgo see if we have created a default sphere for drawing yet...
    //if we haven't then create it..
	if (numpts == 0) 
		GetSpherePoints(Point3(0.0f,0.0f,0.0f), 1.0, SpherePts);

	
	GraphicsWindow *gw = vpt->getGW();
   
	//set the identity matrix...
	Matrix3 idMat;
	idMat.IdentityMatrix();
    gw->setTransform(idMat);

	gw->setColor(LINE_COLOR,.815f,.976f,1.0f);

	float scaleRadius = GetDisplayScale(t);
	
	//set the drawing radius values based upon what the radius size is.
	for (i=0; i<NUMAROUND * 3; i++) ScaledPts[i] = ((SpherePts[i] * scaleRadius));
	 
	//for each follower we need to increase the bounding box by it's
	//world position location...
	for(i =0;i<GetFollowerCount(t);i++)
	{
		INode *followerNode = GetFollower(t,i);
		if(followerNode) //if we have a a node...
		{
	
			Matrix3 leaderMat = GetCurrentMatrix(leaderNode,t);
			leaderMat.NoScale();
			Matrix3 followerMat = GetFollowerMatrix(t,i);
			Matrix3 worldSpace = followerMat *leaderMat;
			for (j=0; j<NUMAROUND * 3; j++) CurPts[j] = worldSpace*ScaledPts[j]; //adding the center to the point positions
			
		   	gw->polyline(NUMAROUND,&CurPts[0],NULL,NULL,TRUE,NULL);
		 	gw->polyline(NUMAROUND,&CurPts[NUMAROUND],NULL,NULL,TRUE,NULL);
    		gw->polyline(NUMAROUND,&CurPts[NUMAROUND * 2],NULL,NULL,TRUE,NULL);

		
		}
	}

	return TRUE;
}
예제 #6
0
dMatrix DemoEntity::CalculateGlobalMatrix (const DemoEntity* const root) const
{
	dMatrix matrix (GetIdentityMatrix());
	for (const DemoEntity* ptr = this; ptr != root; ptr = ptr->GetParent()) {
		matrix = matrix * GetCurrentMatrix ();
	}
	return matrix;
}
예제 #7
0
파일: cgl.cpp 프로젝트: dogtwelve/eepp
eeVector3f cGL::UnProjectCurrent( const eeVector3f& point ) {
	GLfloat projMat[16];
	GetCurrentMatrix( GL_PROJECTION_MATRIX, projMat );

	GLfloat modelMat[16];
	GetCurrentMatrix( GL_MODELVIEW_MATRIX, modelMat );

	GLint viewPort[4];
	GetViewport( viewPort );

	eeVector3f fPoint( point );
	fPoint.y = viewPort[3] - point.y;

	Vector3<GLfloat> tv3;

	UnProject( (GLfloat)fPoint.x, (GLfloat)fPoint.y, (GLfloat)fPoint.z, projMat, modelMat, viewPort, &tv3.x, &tv3.y, &tv3.z );

	return eeVector3f( tv3.x, tv3.y, tv3.z );
}
예제 #8
0
HRESULT CScoringStar::RenderCageObject( LPDIRECT3DDEVICE8 pd3dDevice, BOOL bDrawOpaqueSubsets /*= TRUE*/, BOOL bDrawAlphaSubsets /*= TRUE*/ )
{
	static D3DXVECTOR3 firstScoringStar(-14,-15,-150);
	static int spacingX = 3;
	D3DXMATRIX matWorld,tempMatView;

	// set view transform such that stars are positioned releative to camera
	D3DXMatrixLookAtLH( &tempMatView, m_pCageApp->GetCameraPosition(),&D3DXVECTOR3( 0, 0, 0),&D3DXVECTOR3( 0, 1, 0 ) );
	pd3dDevice->SetTransform( D3DTS_VIEW,  &tempMatView);

	if (m_bIsDark)
	{
		for (int i=m_pCageApp->GetNumCaught(); i<m_pCageApp->GetNumToWin(); i++)
		{
			m_Position = firstScoringStar;
			m_Position.x += (spacingX*i);
			GetCurrentMatrix(&matWorld);
		    pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );			
			CCageObject::Render(pd3dDevice);			
		}
	}
	else
	{
		for (int i=0; i<m_pCageApp->GetNumCaught(); i++)
		{
			m_Position = firstScoringStar;
			m_Position.x += (spacingX*i);
			GetCurrentMatrix(&matWorld);
		    pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
			CCageObject::Render(pd3dDevice);
		}
	}

	// restore original view transform
	pd3dDevice->SetTransform( D3DTS_VIEW,  m_pCageApp->GetViewMatrix());

	return S_OK;
}
예제 #9
0
void Render::Line(float x1, float y1, float x2, float y2, DWORD color) {
    GetCurrentMatrix().Mul(x1, y1, x1, y1);
    GetCurrentMatrix().Mul(x2, y2, x2, y2);
    if (_lineCachEnable)
    {
        LineCach cach;
        cach.start.x = x1;
        cach.start.y = y1;
        cach.end.x = x2;
        cach.end.y = y2;
        cach.color = color;
        _linesCach.push_back(cach);
        return;
    }
    Render::PushColorAndMul(color);
    DWORD currentColor = Render::GetColor();
    glColor4ubv( (GLubyte*)&currentColor );
    glBegin(GL_LINES);
    glVertex2d(x1, y1);
    glVertex2d(x2, y2);
    glEnd();
    Render::PopColor();
}
	void SimulationLister(DemoEntityManager* const scene, DemoEntityManager::dListNode* const mynode, dFloat timeStep)
	{
		m_delay --;
		if (m_delay > 0) {
			return;
		}

		// see if the net force on the body comes fr a high impact collision
		dFloat maxInternalForce = 0.0f;
		for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(m_myBody); joint; joint = NewtonBodyGetNextContactJoint(m_myBody, joint)) {
			for (void* contact = NewtonContactJointGetFirstContact (joint); contact; contact = NewtonContactJointGetNextContact (joint, contact)) {
				//dVector point;
				//dVector normal;	
				dVector contactForce;
				NewtonMaterial* const material = NewtonContactGetMaterial (contact);
				//NewtonMaterialGetContactPositionAndNormal (material, &point.m_x, &normal.m_x);
				NewtonMaterialGetContactForce(material, m_myBody, &contactForce[0]);
				dFloat forceMag = contactForce % contactForce;
				if (forceMag > maxInternalForce) {
					maxInternalForce = forceMag;
				}
			}
		}

		

		// if the force is bigger than 4 Gravities, It is considered a collision force
		dFloat maxForce = BREAK_FORCE_IN_GRAVITIES * m_myweight;

		if (maxInternalForce > (maxForce * maxForce)) {
			NewtonWorld* const world = NewtonBodyGetWorld(m_myBody);

			dFloat Ixx; 
			dFloat Iyy; 
			dFloat Izz; 
			dFloat mass; 
			NewtonBodyGetMassMatrix(m_myBody, &mass, &Ixx, &Iyy, &Izz);

			dVector com;
			dVector veloc;
			dVector omega;
			dMatrix bodyMatrix;

			NewtonBodyGetVelocity(m_myBody, &veloc[0]);
			NewtonBodyGetOmega(m_myBody, &omega[0]);
			NewtonBodyGetCentreOfMass(m_myBody, &com[0]);
			NewtonBodyGetMatrix(m_myBody, &bodyMatrix[0][0]);
			com = bodyMatrix.TransformVector (com);

			dMatrix matrix (GetCurrentMatrix());
			dQuaternion rotation (matrix);
			for (ShatterEffect::dListNode* node = m_effect.GetFirst(); node; node = node->GetNext()) {
				ShatterAtom& atom = node->GetInfo();

				DemoEntity* const entity = new DemoEntity (NULL);
				entity->SetMesh (atom.m_mesh);
				entity->SetMatrix(*scene, rotation, matrix.m_posit);
				entity->InterpolateMatrix (*scene, 1.0f);
				scene->Append(entity);

				int materialId = 0;

				dFloat debriMass = mass * atom.m_massFraction;
				dFloat Ixx = debriMass * atom.m_momentOfInirtia.m_x;
				dFloat Iyy = debriMass * atom.m_momentOfInirtia.m_y;
				dFloat Izz = debriMass * atom.m_momentOfInirtia.m_z;

				//create the rigid body
				NewtonBody* const rigidBody = NewtonCreateBody (world, atom.m_collision, &matrix[0][0]);

				// set the correct center of gravity for this body
				NewtonBodySetCentreOfMass (rigidBody, &atom.m_centerOfMass[0]);

				// calculate the center of mas of the debris
				dVector center (matrix.TransformVector(atom.m_centerOfMass));

				// calculate debris initial velocity
				dVector v (veloc + omega * (center - com));

				// set initial velocity
				NewtonBodySetVelocity(rigidBody, &v[0]);
				NewtonBodySetOmega(rigidBody, &omega[0]);

				// set the  debrie center of mass
				NewtonBodySetCentreOfMass (rigidBody, &atom.m_centerOfMass[0]);


				// set the mass matrix
				NewtonBodySetMassMatrix (rigidBody, debriMass, Ixx, Iyy, Izz);

				// activate 
				//	NewtonBodyCoriolisForcesMode (blockBoxBody, 1);

				// save the pointer to the graphic object with the body.
				NewtonBodySetUserData (rigidBody, entity);

				// assign the wood id
				NewtonBodySetMaterialGroupID (rigidBody, materialId);

				//  set continue collision mode
				//	NewtonBodySetContinuousCollisionMode (rigidBody, continueCollisionMode);

				// set a destructor for this rigid body
				NewtonBodySetDestructorCallback (rigidBody, PhysicsBodyDestructor);

				// set the transform call back function
				NewtonBodySetTransformCallback (rigidBody, DemoEntity::SetTransformCallback);

				// set the force and torque call back function
				NewtonBodySetForceAndTorqueCallback (rigidBody, PhysicsApplyGravityForce);
			}

			NewtonDestroyBody(world, m_myBody);
			scene->RemoveEntity	(mynode);
		}
	};
예제 #11
0
int FormationBhvr::Perform(INode *node, TimeValue t, int numsubsamples, BOOL DisplayHelpers, float BhvrWeight,
			PerformOut &out)
{
	Object *o = node->GetObjectRef();
    if (o->ClassID() != DELEG_CLASSID) return FALSE; // this should never happen
    IDelegate *IDeleg = (IDelegate *) o->GetInterface(I_DELEGINTERFACE);
	Point3 vel= IDeleg->GetCurrentVelocity();

	Point3 pos = IDeleg->GetCurrentPosition();

	INode *leader = GetLeader(t);
	if(leader==NULL)
		return 0;

	
	Matrix3 formationMat;
	//Get the local formation matrix and check

	if(FindFollowerMatrix(t,node,formationMat)==FALSE)
		return 0; //that node doesn't exist in the formation so exit.

	//returned values.
	Point3 frc,goal;
	float speedwt, speedAtGoalwt;

	//Find the Formation Position Target in World Space.

 	Matrix3 currentLeaderMat = GetCurrentMatrix(leader,t);
	currentLeaderMat.NoScale();
	Matrix3 worldSpace = formationMat*currentLeaderMat;
	Point3 target =  worldSpace.GetTrans();

	//set the goal as the target
	goal = target;

	//set the force as the direction to move towards the target
	frc =  goal - pos;

	float length = frc.FLength();

	if(length!=0.0f) //we are not at the goal
	{
		frc  /=length;
		
		//set up the leader Vector
		Point3 leaderVec = leaderVel*leaderSpeed;

	
	
		//If the  target is behind you but moving towards you don't turn around to
		//go toward it.  Instead move in the direction of the leader.
		if(frc%vel<0.0f &&  //if you are behind it
			length/IDeleg->GetAverageSpeed(t)<10 && //AND less than 20 frames
			vel%leaderVel>0.0f) //AND it is going toward you.
		{
			
			//set frc as leader's Velocity.
			frc = leaderVel;

			//move at half the leaderSpeed.  Leader will still catch
			//up to you and you'll have some speed when it does.
			
			//set the speewt
			speedwt = (leaderSpeed*0.5f)/IDeleg->GetAverageSpeed(t);
		}
		else //we should just move towards the target.
		{
			//We need to find the speed to be it.  We do this by
			//finding the time we will intersect our target based
			//upon the leader's velocity and our own velocity.

			vel -= leaderVec;
			
			//find time to intersect..
			float newSpeed = vel.FLength();
			float timeToIntersect = length/newSpeed;

			//from that time.. figure out what it speed should be..
			newSpeed = timeToIntersect * IDeleg->GetMaxAccel(t);
			if(newSpeed>IDeleg->GetAverageSpeed(t))
				newSpeed = IDeleg->GetAverageSpeed(t);


			//check to see if we will move past the goal.. if so
			//move the goal along the leader vec.  This reduces overshooting
			//the goal and decreases wobbling.
			if((newSpeed+leaderSpeed)>length) 	
			{
				goal += leaderVel*(leaderSpeed);  
				frc = goal -pos;
				float newLength = frc.FLength();

				if(newLength!=0.0f) //check for if zero to avoid divide by zero..
				{
					frc /= newLength;
					speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
										
				}
				else
				{
					speedwt = 0.0f;
				}

			}
			else //far enough away.. leave the ole frc value..
				speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
			
		}
	}
	else  //we are at the goal
	{
		frc.x = frc.y = frc.z = 0.0f;
	
		//set the speedwt to be the leaderSpeed
		speedwt = leaderSpeed/IDeleg->GetAverageSpeed(t);
	}

	frc *= BhvrWeight *IDeleg->GetAverageSpeed(t); //scale by weight and average speed..

	//set the speedWtAtGoal.. We want it to be the speed of the leader
	speedAtGoalwt = leaderSpeed/IDeleg->GetAverageSpeed(t);

	//Display Any Helpers.
	if (DisplayHelpers && IDeleg->OkToDisplayMyForces())
	{
		if (DisplayTarget(t)) IDeleg->SphereDisplay(goal,pblock->GetFloat(target_scale),GetTargetColor(t));
		if (DisplayForce(t))  IDeleg->LineDisplay(IDeleg->GetCurrentPosition(),IDeleg->GetCurrentPosition()+frc,GetForceColor(t),TRUE);
	}

	//set up the out structure..
	out.frc = frc;
	out.goal = goal;
	out.speedwt = speedwt;
	out.speedAtGoalwt = speedAtGoalwt;

	return BHVR_SETS_FORCE | BHVR_SETS_GOAL | BHVR_SETS_SPEED;
}
	void SimulationPostListener(DemoEntityManager* const scene, DemoEntityManager::dListNode* const mynode, dFloat timeStep)
	{
		// see if the net force on the body comes fr a high impact collision
		dFloat breakImpact = 0.0f;
		for (NewtonJoint* joint = NewtonBodyGetFirstContactJoint(m_myBody); joint; joint = NewtonBodyGetNextContactJoint(m_myBody, joint)) {
			for (void* contact = NewtonContactJointGetFirstContact(joint); contact; contact = NewtonContactJointGetNextContact(joint, contact)) {
				dVector contactForce;
				NewtonMaterial* const material = NewtonContactGetMaterial(contact);
				dFloat impulseImpact = NewtonMaterialGetContactMaxNormalImpact(material);
				if (impulseImpact > breakImpact) {
					breakImpact = impulseImpact;
				}
			}
		}


		// if the force is bigger than N time Gravities, It is considered a collision force
		breakImpact *= m_myMassInverse;
//		breakImpact = 1000.0f;
		if (breakImpact > BREAK_IMPACT_IN_METERS_PER_SECONDS) {
			NewtonWorld* const world = NewtonBodyGetWorld(m_myBody);

			dMatrix bodyMatrix;
			dVector com(0.0f);
			dVector veloc(0.0f);
			dVector omega(0.0f);
			dFloat Ixx;
			dFloat Iyy;
			dFloat Izz;
			dFloat mass;

			NewtonBodyGetVelocity(m_myBody, &veloc[0]);
			NewtonBodyGetOmega(m_myBody, &omega[0]);
			NewtonBodyGetCentreOfMass(m_myBody, &com[0]);
			NewtonBodyGetMatrix(m_myBody, &bodyMatrix[0][0]);
			NewtonBodyGetMass(m_myBody, &mass, &Ixx, &Iyy, &Izz);

			com = bodyMatrix.TransformVector(com);
			dMatrix matrix(GetCurrentMatrix());
			dQuaternion rotation(matrix);

			// we need to lock the world before creation a bunch of bodies
			scene->Lock(m_lock);

			for (FractureEffect::dListNode* node = m_effect.GetFirst(); node; node = node->GetNext()) {
				FractureAtom& atom = node->GetInfo();

				DemoEntity* const entity = new DemoEntity(dMatrix(rotation, matrix.m_posit), NULL);
				entity->SetMesh(atom.m_mesh, dGetIdentityMatrix());
				scene->Append(entity);

				int materialId = 0;

				dFloat debriMass = mass * atom.m_massFraction;

				//create the rigid body
				NewtonBody* const rigidBody = NewtonCreateDynamicBody(world, atom.m_collision, &matrix[0][0]);

				// calculate debris initial velocity
				dVector center(matrix.TransformVector(atom.m_centerOfMass));
				dVector v(veloc + omega.CrossProduct(center - com));

				// set initial velocity
				NewtonBodySetVelocity(rigidBody, &v[0]);
				NewtonBodySetOmega(rigidBody, &omega[0]);

				// set the debris mass properties, mass, center of mass, and inertia 
				NewtonBodySetMassProperties(rigidBody, debriMass, atom.m_collision);

				// save the pointer to the graphic object with the body.
				NewtonBodySetUserData(rigidBody, entity);

				// assign the wood id
				NewtonBodySetMaterialGroupID(rigidBody, materialId);

				//  set continuous collision mode
				//	NewtonBodySetContinuousCollisionMode (rigidBody, continueCollisionMode);

				// set a destructor for this rigid body
				NewtonBodySetDestructorCallback(rigidBody, PhysicsBodyDestructor);

				// set the transform call back function
				NewtonBodySetTransformCallback(rigidBody, DemoEntity::TransformCallback);

				// set the force and torque call back function
				NewtonBodySetForceAndTorqueCallback(rigidBody, PhysicsApplyGravityForce);
			}

			NewtonDestroyBody(m_myBody);
			scene->RemoveEntity(mynode);

			// unlock the work after done with the effect 
			scene->Unlock(m_lock);
		}
	}
예제 #13
0
KVDetector* KVGeoImport::GetCurrentDetector()
{
    // Returns pointer to KVDetector corresponding to current location
    // in geometry. Detector is created and added to array if needed.
    // We also set up any geometry structure elements (from nodes beginning with "STRUCT_")

    KVString detector_name;
    Bool_t multilay;
    TGeoVolume* detector_volume = GetCurrentDetectorNameAndVolume(detector_name,multilay);
    // failed to identify current volume as part of a detector
    if(!detector_volume) return 0;

    // has detector already been built ? if not, do it now
    KVDetector* det = fArray->GetDetector(detector_name);
    if(!fCreateArray){
        if(det){
            // set matrix & shape for entrance window if not done yet
            if(!det->GetEntranceWindowMatrix()){
                det->SetEntranceWindowMatrix(GetCurrentMatrix());
                det->SetEntranceWindowShape((TGeoBBox*)GetCurrentVolume()->GetShape());
            }
            TString vol_name(GetCurrentVolume()->GetName());
            if(!multilay || vol_name.BeginsWith("ACTIVE_")){
                // set matrix & shape for active layer
                det->SetActiveLayerMatrix(GetCurrentMatrix());
                det->SetActiveLayerShape((TGeoBBox*)GetCurrentVolume()->GetShape());
            }
        }
    }
    else
    {
        if(!det) {
            det = BuildDetector(detector_name, detector_volume);
            if(det) {
                // Setting the entrance window shape and matrix
                // ============================================
                // for consistency, the matrix and shape MUST correspond
                // i.e. we cannot have the matrix corresponding to the entrance window
                // of a multilayer detector and the shape corresponding to the
                // whole detector (all layers) - otherwise, calculation of points
                // on detector entrance window will be false!
//                Info("GetCurrentDetector","Setting EW matrix to current matrix:");
//                GetCurrentMatrix()->Print();
                det->SetEntranceWindowMatrix(GetCurrentMatrix());
                det->SetEntranceWindowShape((TGeoBBox*)GetCurrentVolume()->GetShape());
                TString vol_name(GetCurrentVolume()->GetName());
                if(!multilay || vol_name.BeginsWith("ACTIVE_")){
                    // first layer of detector (or only layer) is also active layer
//                    Info("GetCurrentDetector","and also setting active layer matrix to current matrix:");
//                    GetCurrentMatrix()->Print();
                    det->SetActiveLayerMatrix(GetCurrentMatrix());
                    det->SetActiveLayerShape((TGeoBBox*)GetCurrentVolume()->GetShape());
                }
                fArray->Add(det);
                Int_t nstruc = CurrentStructures().GetEntries();
                if(nstruc){
                    // Build and add geometry structure elements
                    KVGeoStrucElement* ELEM = fArray;
                    for(register int i=0;i<nstruc;i++){
                        KVGeoStrucElement* elem = (KVGeoStrucElement*)CurrentStructures()[i];
                        KVGeoStrucElement* nextELEM = ELEM->GetStructure(elem->GetName());
                        if(!nextELEM){
                            // make new structure
                            nextELEM = new KVGeoStrucElement(elem->GetName(), elem->GetType());
                            nextELEM->SetNumber(elem->GetNumber());
                            ELEM->Add(nextELEM);
                        }
                        ELEM=nextELEM;
                    }
                    // add detector to last structure
                    ELEM->Add(det);
                }
            }
        }
        else
        {
            // Detector already built, are we now in its active layer ?
            TString vol_name(GetCurrentVolume()->GetName());
            if(!multilay || vol_name.BeginsWith("ACTIVE_")){
//                Info("GetCurrentDetector","Setting active layer matrix to current matrix:");
//                GetCurrentMatrix()->Print();
                det->SetActiveLayerMatrix(GetCurrentMatrix());
                det->SetActiveLayerShape((TGeoBBox*)GetCurrentVolume()->GetShape());
            }
        }
    }
    return det;
}