예제 #1
0
//-------------------------------------------------------------------------------------
static void generate_orthonormal_basis(const Fvector& dir,Fmatrix &result)
{
    result.identity		();
    result.k.normalize	(dir);
    Fvector::generate_orthonormal_basis(result.k, result.j, result.i);
}
예제 #2
0
void CLensFlare::OnFrame(int id)
{
	if (dwFrame==Device.dwFrame)return;
#ifndef _EDITOR
	if (!g_pGameLevel)			return;
#endif
	dwFrame			= Device.dwFrame;

	vSunDir.mul		(g_pGamePersistent->Environment().CurrentEnv.sun_dir,-1);

	// color
    float tf		= g_pGamePersistent->Environment().fTimeFactor;
    Fvector& c		= g_pGamePersistent->Environment().CurrentEnv.sun_color;
	LightColor.set	(c.x,c.y,c.z,1.f); 

    CLensFlareDescriptor* desc = (id==-1)?0:&m_Palette[id];

    switch(m_State){
    case lfsNone: m_State=lfsShow; m_Current=desc; break;
    case lfsIdle: if (desc!=m_Current) m_State=lfsHide; 	break;
    case lfsShow: 
        m_StateBlend 	= m_Current?(m_StateBlend + m_Current->m_StateBlendUpSpeed * Device.fTimeDelta * tf):1.f+EPS;
        if (m_StateBlend>=1.f) m_State=lfsIdle;
    break;
    case lfsHide: 
        m_StateBlend 	= m_Current?(m_StateBlend - m_Current->m_StateBlendDnSpeed * Device.fTimeDelta * tf):0.f-EPS;
        if (m_StateBlend<=0.f){ 	
            m_State		= lfsShow;
            m_Current	= desc;
	        m_StateBlend= m_Current?m_Current->m_StateBlendUpSpeed * Device.fTimeDelta * tf:0;
        }
    break;
    }
    clamp(m_StateBlend,0.f,1.f);

    if ((m_Current==0)||(LightColor.magnitude_rgb()==0.f)){bRender=false; return;}

	//
	// Compute center and axis of flares
	//
	float fDot;

	Fvector vecPos;

	Fmatrix	matEffCamPos;
	matEffCamPos.identity();
	// Calculate our position and direction

	matEffCamPos.i.set(Device.vCameraRight);
	matEffCamPos.j.set(Device.vCameraTop);
	matEffCamPos.k.set(Device.vCameraDirection);
	vecPos.set(Device.vCameraPosition);

	vecDir.set(0.0f, 0.0f, 1.0f);
	matEffCamPos.transform_dir(vecDir);
	vecDir.normalize();

	// Figure out of light (or flare) might be visible
	vecLight.set(vSunDir);
	vecLight.normalize();

	fDot = vecLight.dotproduct(vecDir);

	if(fDot <= 0.01f){	bRender = false; return;} else bRender = true;

	// Calculate the point directly in front of us, on the far clip plane
	float 	fDistance	= FAR_DIST*0.75f;
	vecCenter.mul(vecDir, fDistance);
	vecCenter.add(vecPos);
	// Calculate position of light on the far clip plane
	vecLight.mul(fDistance / fDot);
	vecLight.add(vecPos);
	// Compute axis which goes from light through the center of the screen
	vecAxis.sub(vecLight, vecCenter);

	//
	// Figure out if light is behind something else
	vecX.set(1.0f, 0.0f, 0.0f);
	matEffCamPos.transform_dir(vecX);
	vecX.normalize();
	vecY.crossproduct(vecX, vecDir);

#ifdef _EDITOR
	float dist = UI->ZFar();
    if (Tools->RayPick(Device.m_Camera.GetPosition(),vSunDir,dist))
		fBlend = fBlend - BLEND_DEC_SPEED * Device.fTimeDelta;
	else
		fBlend = fBlend + BLEND_INC_SPEED * Device.fTimeDelta;
#else
	CObject*	o_main		= g_pGameLevel->CurrentViewEntity();
	STranspParam TP			(this,Device.vCameraPosition,vSunDir,1000.f,EPS_L);
	collide::ray_defs RD	(TP.P,TP.D,TP.f,CDB::OPT_CULL,collide::rqtBoth);
	if (m_ray_cache.result&&m_ray_cache.similar(TP.P,TP.D,TP.f)){
		// similar with previous query == 0
		TP.vis				= 0.f;
	}else{
		float _u,_v,_range;
		if (CDB::TestRayTri(TP.P,TP.D,m_ray_cache.verts,_u,_v,_range,false)&&(_range>0 && _range<TP.f)){
			TP.vis			= 0.f;
		}else{
			// cache outdated. real query.
			r_dest.r_clear	();
			if (g_pGameLevel->ObjectSpace.RayQuery	(r_dest,RD,material_callback,&TP,NULL,o_main))
				m_ray_cache.result = FALSE			;
		}
	}
	blend_lerp(fBlend,TP.vis,BLEND_DEC_SPEED,Device.fTimeDelta);

#endif
	clamp( fBlend, 0.0f, 1.0f );

	// gradient
	if (m_Current->m_Flags.is(CLensFlareDescriptor::flGradient))
    {
		Fvector				scr_pos;
		Device.mFullTransform.transform	( scr_pos, vecLight );
		float kx = 1, ky = 1;
		float sun_blend		= 0.5f;
		float sun_max		= 2.5f;
		scr_pos.y			*= -1;

		if (_abs(scr_pos.x) > sun_blend)	kx = ((sun_max - (float)_abs(scr_pos.x))) / (sun_max - sun_blend);
		if (_abs(scr_pos.y) > sun_blend)	ky = ((sun_max - (float)_abs(scr_pos.y))) / (sun_max - sun_blend);

		if (!((_abs(scr_pos.x) > sun_max) || (_abs(scr_pos.y) > sun_max))){
        	float op		= m_StateBlend*m_Current->m_Gradient.fOpacity;
			fGradientValue	= kx * ky *  op * fBlend;
		}else
			fGradientValue	= 0;
	}
}
예제 #3
0
void CBurer::UpdateGraviObject()
{
	if ( !m_gravi_object.active ) 
	{
		return;
	}
	
	if ( !m_gravi_object.enemy || (m_gravi_object.enemy && m_gravi_object.enemy->getDestroy()) ) 
	{
		m_gravi_object.deactivate();
		return;
	}

	if ( m_gravi_object.from_pos.distance_to(m_gravi_object.cur_pos) 
				> 
		 m_gravi_object.from_pos.distance_to(m_gravi_object.target_pos) ) 
	{
		m_gravi_object.deactivate();
		return;
	}

	float dt = float(Device.dwTimeGlobal - m_gravi_object.time_last_update);
	float dist = dt * float(m_gravi.speed)/1000.f;
		
	if (dist < m_gravi.step) return;
	
	Fvector new_pos;
	Fvector dir;
	dir.sub(m_gravi_object.target_pos,m_gravi_object.cur_pos);
	dir.normalize();
	
	new_pos.mad(m_gravi_object.cur_pos,dir,dist);

	// Trace to enemy 
	Fvector enemy_center;
	m_gravi_object.enemy->Center(enemy_center);
	dir.sub(enemy_center, new_pos);
	dir.normalize();

	float trace_dist = float(m_gravi.step);

	collide::rq_result	l_rq;
	if (Level().ObjectSpace.RayPick(new_pos, dir, trace_dist, collide::rqtBoth, l_rq, NULL)) {
		const CObject *enemy = smart_cast<const CObject *>(m_gravi_object.enemy);
		if ((l_rq.O == enemy) && (l_rq.range < trace_dist)) {
			
			// check for visibility
			bool b_enemy_visible = false;
			xr_vector<CObject *> visible_objects;
			feel_vision_get(visible_objects);

			// find object
			for (u32 i = 0; i<visible_objects.size(); i++) {
				if (visible_objects[i] == enemy) {
					b_enemy_visible = true;
					break;
				}
			}
			
			if (b_enemy_visible) {
				Fvector impulse_dir;

				impulse_dir.set(0.0f,0.0f,1.0f);
				impulse_dir.normalize();

				HitEntity(m_gravi_object.enemy, m_gravi.hit_power, m_gravi.impulse_to_enemy, impulse_dir, ALife::eHitTypeStrike, false);
				m_gravi_object.deactivate();
				return;
			}
		}
	}
																								
	m_gravi_object.cur_pos				= new_pos;
	m_gravi_object.time_last_update		= Device.dwTimeGlobal;

	// ---------------------------------------------------------------------
	// draw particle
	CParticlesObject* ps = CParticlesObject::Create(particle_gravi_wave,TRUE);

	// вычислить позицию и направленность партикла
	Fmatrix pos; 
	pos.identity();
	pos.k.set(dir);
	Fvector::generate_orthonormal_basis_normalized(pos.k,pos.j,pos.i);
	// установить позицию
	pos.translate_over(m_gravi_object.cur_pos);

	ps->UpdateParent(pos, zero_vel);
	ps->Play(false);
	
	// hit objects
	m_nearest.clear_not_free		();
	Level().ObjectSpace.GetNearest	(m_nearest,m_gravi_object.cur_pos, m_gravi.radius, NULL); 
	//xr_vector<CObject*> &m_nearest = Level().ObjectSpace.q_nearest;

	for (u32 i=0;i<m_nearest.size();i++) {
		CPhysicsShellHolder  *obj = smart_cast<CPhysicsShellHolder *>(m_nearest[i]);
		if (!obj || !obj->m_pPhysicsShell) continue;
		
		Fvector dir;
		dir.sub(obj->Position(), m_gravi_object.cur_pos);
		dir.normalize();
		obj->m_pPhysicsShell->applyImpulse(dir,m_gravi.impulse_to_objects * obj->m_pPhysicsShell->getMass());
	}

	// играть звук
	Fvector snd_pos = m_gravi_object.cur_pos;
	snd_pos.y += 0.5f;
	if (sound_gravi_wave._feedback())		{
		sound_gravi_wave.set_position	(snd_pos);
	} else ::Sound->play_at_pos			(sound_gravi_wave,0,snd_pos);
}
예제 #4
0
BOOL CAlienEffector::ProcessCam(SCamEffectorInfo& info)
{
	// »нициализаци¤
	Fmatrix	Mdef;
	Mdef.identity		();
	Mdef.j.set			(info.n);
	Mdef.k.set			(info.d);
	Mdef.i.crossproduct	(info.n, info.d);
	Mdef.c.set			(info.p);


	// set angle 
	if (angle_lerp(dangle_current.x, dangle_target.x, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.x = angle_normalize(Random.randFs(DELTA_ANGLE_X));
	}

	if (angle_lerp(dangle_current.y, dangle_target.y, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.y = angle_normalize(Random.randFs(DELTA_ANGLE_Y));
	}

	if (angle_lerp(dangle_current.z, dangle_target.z, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.z = angle_normalize(Random.randFs(DELTA_ANGLE_Z));
	}

	// update inertion
	Fmatrix cur_matrix;
	cur_matrix.k = monster->Direction();
	cur_matrix.c = get_head_position(monster);

	float	rel_dist = m_prev_eye_matrix.c.distance_to(cur_matrix.c) / MAX_CAMERA_DIST;
	clamp	(rel_dist, 0.f, 1.f);

	def_lerp(m_inertion, 1 - rel_dist, rel_dist, Device.fTimeDelta);

	// set pos and dir with inertion
	m_prev_eye_matrix.c.inertion(cur_matrix.c, m_inertion);
	m_prev_eye_matrix.k.inertion(cur_matrix.k, m_inertion);
	Fvector::generate_orthonormal_basis_normalized(m_prev_eye_matrix.k,m_prev_eye_matrix.j,m_prev_eye_matrix.i);	

	// apply position and direction
	Mdef = m_prev_eye_matrix;

	//set fov
	float	rel_speed = monster->m_fCurSpeed / 15.f;
	clamp	(rel_speed,0.f,1.f);

	float	m_target_fov = MIN_FOV + (MAX_FOV-MIN_FOV) * rel_speed;
	def_lerp(m_current_fov, m_target_fov, FOV_SPEED, Device.fTimeDelta);
	
	info.fFov = m_current_fov;
	//////////////////////////////////////////////////////////////////////////

	// ”становить углы смещени¤
	Fmatrix		R;
	R.setHPB	(dangle_current.x,dangle_current.y,dangle_current.z);

	Fmatrix		mR;
	mR.mul		(Mdef,R);

	info.d.set		(mR.k);
	info.n.set		(mR.j);
	info.p.set		(mR.c);

	return TRUE;
}
예제 #5
0
void CSphereGeom::get_local_form(Fmatrix& form)
{
	form.identity();
	form.c.set(m_sphere.P);
}
예제 #6
0
BOOL CEffectorBobbing::Process		(Fvector &p, Fvector &d, Fvector &n, float& /**fFov/**/, float& /**fFar/**/, float& /**fAspect/**/)
{
	fTime			+= Device.fTimeDelta;
	if (dwMState&ACTOR_DEFS::mcAnyMove){
		if (fReminderFactor<1.f)	fReminderFactor += SPEED_REMINDER*Device.fTimeDelta;
		else						fReminderFactor = 1.f;
	}else{
		if (fReminderFactor>0.f)	fReminderFactor -= SPEED_REMINDER*Device.fTimeDelta;
		else						fReminderFactor = 0.f;
	}
	if (!fsimilar(fReminderFactor,0)){
		Fmatrix		M;
		M.identity	();
		M.j.set		(n);
		M.k.set		(d);
		M.i.crossproduct(n,d);
		M.c.set		(p);
		
		// apply footstep bobbing effect
		Fvector dangle;
		float k		= ((dwMState& ACTOR_DEFS::mcCrouch)?CROUCH_FACTOR:1.f);

		float A, ST;

		if(isActorAccelerated(dwMState, m_bZoomMode))
		{
			A	= m_fAmplitudeRun*k;
			ST	= m_fSpeedRun*fTime*k;
		}
		else if(is_limping)
		{
			A	= m_fAmplitudeLimp*k;
			ST	= m_fSpeedLimp*fTime*k;
		}
		else
		{
			A	= m_fAmplitudeWalk*k;
			ST	= m_fSpeedWalk*fTime*k;
		}
	
		float _sinA	= _abs(_sin(ST)*A)*fReminderFactor;
		float _cosA	= _cos(ST)*A*fReminderFactor;

		p.y			+=	_sinA;
		dangle.x	=	_cosA;
		dangle.z	=	_cosA;
		dangle.y	=	_sinA;

		Fmatrix		R;
		R.setHPB	(dangle.x,dangle.y,dangle.z);

		Fmatrix		mR;
		mR.mul		(M,R);
		
		d.set		(mR.k);
		n.set		(mR.j);
	}
//	else{
//		fTime		= 0;
//	}
	return TRUE;
}
예제 #7
0
void render_box						(IRenderVisual *visual, const Fmatrix &xform, const Fvector &additional, bool draw_child_boxes, const u32 &color)
{
	CDebugRenderer			&renderer = Level().debug_renderer();
	IKinematics				*kinematics = smart_cast<IKinematics*>(visual);
	VERIFY					(kinematics);
	u16						bone_count = kinematics->LL_BoneCount();
	VERIFY					(bone_count);
	u16						visible_bone_count = kinematics->LL_VisibleBoneCount();
	if (!visible_bone_count)
		return;

	Fmatrix					matrix;
	Fvector					*points = (Fvector*)_alloca(visible_bone_count*8*sizeof(Fvector));
	Fvector					*I = points;
	for (u16 i=0; i<bone_count; ++i) {
		if (!kinematics->LL_GetBoneVisible(i))
			continue;
		
		const Fobb			&obb = kinematics->LL_GetData(i).obb;
		if (fis_zero(obb.m_halfsize.square_magnitude())) {
			VERIFY			(visible_bone_count > 1);
			--visible_bone_count;
			continue;
		}

		Fmatrix				Mbox;
		obb.xform_get		(Mbox);

		const Fmatrix		&Mbone = kinematics->LL_GetBoneInstance(i).mTransform;
		Fmatrix				X;
		matrix.mul_43		(xform,X.mul_43(Mbone,Mbox));

		Fvector				half_size = Fvector().add(obb.m_halfsize,additional);
		matrix.mulB_43		(Fmatrix().scale(half_size));

		if (draw_child_boxes)
			renderer.draw_obb	(matrix,color);

		static const Fvector	local_points[8] = {
			Fvector().set(-1.f,-1.f,-1.f),
			Fvector().set(-1.f,-1.f,+1.f),
			Fvector().set(-1.f,+1.f,+1.f),
			Fvector().set(-1.f,+1.f,-1.f),
			Fvector().set(+1.f,+1.f,+1.f),
			Fvector().set(+1.f,+1.f,-1.f),
			Fvector().set(+1.f,-1.f,+1.f),
			Fvector().set(+1.f,-1.f,-1.f)
		};
		
		for (u32 i=0; i<8; ++i, ++I)
			matrix.transform_tiny	(*I,local_points[i]);
	}

	VERIFY						(visible_bone_count);
	if (visible_bone_count == 1) {
		renderer.draw_obb		(matrix,color);
		return;
	}

	VERIFY						((I - points) == (visible_bone_count*8));
	MagicBox3					box = MagicMinBox(visible_bone_count*8,points);
	box.ComputeVertices			(points);
	
	Fmatrix						result;
	result.identity				();

	result.c					= box.Center();

	result.i.sub(points[3],points[2]).normalize();
	result.j.sub(points[2],points[1]).normalize();
	result.k.sub(points[2],points[6]).normalize();

	Fvector						scale;
	scale.x						= points[3].distance_to(points[2])*.5f;
	scale.y						= points[2].distance_to(points[1])*.5f;
	scale.z						= points[2].distance_to(points[6])*.5f;
	result.mulB_43				(Fmatrix().scale(scale));

	renderer.draw_obb			(result,color);
}
예제 #8
0
void CSpectator::cam_Update	(CActor* A)
{
	if (A){
		const Fmatrix& M			= A->XFORM();
		CCameraBase* pACam			= A->cam_Active();
		CCameraBase* cam			= cameras[cam_active];
		switch(cam_active) {
		case eacFirstEye:{
			Fvector P, D, N;
			pACam->Get				(P, D, N);
			cam->Set				(P, D, N);
			}break;
		case eacLookAt:{
			float y,p,r;
			M.getHPB				(y,p,r);
			cam->Set				(pACam->yaw,pACam->pitch,-r);
			}
		case eacFreeLook:{
			cam->SetParent			(A);
			Fmatrix tmp; tmp.identity();
			
			Fvector point, point1, dangle;
			point.set	(0.f,1.6f,0.f);
			point1.set	(0.f,1.6f,0.f);			
			M.transform_tiny		(point);
			tmp.translate_over(point);
			tmp.transform_tiny		(point1);
			if (!A->g_Alive()) point.set(point1);
			cam->Update				(point,dangle);
			}break;
		}
		//-----------------------------------
		Fvector P, D, N;
		cam->Get(P, D, N);
		cameras[eacFreeFly]->Set(P, D, N);
		cameras[eacFreeFly]->Set(cam->yaw, cam->pitch, 0);
		P.y -= 1.6f;
		XFORM().translate_over(P);
		if (Device.Paused())
		{
			Device.fTimeDelta = m_fTimeDelta;	//fake, to update cam (problem with fov)
			g_pGameLevel->Cameras().UpdateFromCamera(cam);
			Device.fTimeDelta = 0.0f;			//fake, to update cam (problem with fov)
		} else
		{
			g_pGameLevel->Cameras().UpdateFromCamera(cam);
		}
		//-----------------------------------
	} else
	{

		CCameraBase* cam			= cameras[eacFreeFly];
		if (cam_active == eacFixedLookAt)
		{
			cam	= cameras[eacFixedLookAt];
		}

		Fvector point, dangle;
		point.set				(0.f,1.6f,0.f);
		XFORM().transform_tiny	(point);

		// apply shift
		dangle.set					(0,0,0);
		
		cam->Update					(point,dangle);
//		cam->vPosition.set(point0);
		if (Device.Paused())
		{
			Device.fTimeDelta = m_fTimeDelta;	//fake, to update cam (problem with fov)
			g_pGameLevel->Cameras().UpdateFromCamera(cam);
			Device.fTimeDelta = 0.0f;			//fake, to update cam (problem with fov)
		} else
		{
			g_pGameLevel->Cameras().UpdateFromCamera(cam);
		}
		// hud output
	};
}
예제 #9
0
void CParticleEffect::Render(float )
{
	u32			dwOffset,dwCount;
	// Get a pointer to the particles in gp memory
    PAPI::Particle* particles;
    u32 			p_cnt;
    ParticleManager()->GetParticles(m_HandleEffect,particles,p_cnt);
    
	if(p_cnt>0){
		if (m_Def&&m_Def->m_Flags.is(CPEDef::dfSprite)){
			FVF::LIT* pv_start	= (FVF::LIT*)RCache.Vertex.Lock(p_cnt*4*4,geom->vb_stride,dwOffset);
			FVF::LIT* pv		= pv_start;

			for(u32 i = 0; i < p_cnt; i++){
				PAPI::Particle &m = particles[i];

				Fvector2 lt,rb;
				lt.set			(0.f,0.f);
				rb.set			(1.f,1.f);
				if (m_Def->m_Flags.is(CPEDef::dfFramed)) m_Def->m_Frame.CalculateTC(iFloor(float(m.frame)/255.f),lt,rb);
				float r_x		= m.size.x*0.5f;
				float r_y		= m.size.y*0.5f;
				if (m_Def->m_Flags.is(CPEDef::dfVelocityScale)){
					float speed	= m.vel.magnitude();
					r_x			+= speed*m_Def->m_VelocityScale.x;
					r_y			+= speed*m_Def->m_VelocityScale.y;
				}
				if (m_Def->m_Flags.is(CPEDef::dfAlignToPath)){
					float speed	= m.vel.magnitude();
                    if ((speed<EPS_S)&&m_Def->m_Flags.is(CPEDef::dfWorldAlign)){
                    	Fmatrix	M;  	
                        M.setXYZ			(m_Def->m_APDefaultRotation);
                        if (m_RT_Flags.is(flRT_XFORM)){
                            Fvector p;
                            m_XFORM.transform_tiny(p,m.pos);
	                        M.mulA_43		(m_XFORM);
                            FillSprite		(pv,M.k,M.i,p,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }else{
                            FillSprite		(pv,M.k,M.i,m.pos,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }
                    }else if ((speed>=EPS_S)&&m_Def->m_Flags.is(CPEDef::dfFaceAlign)){
                    	Fmatrix	M;  		M.identity();
                        M.k.div				(m.vel,speed);            
                        M.j.set 			(0,1,0);	if (_abs(M.j.dotproduct(M.k))>.99f)  M.j.set(0,0,1);
                        M.i.crossproduct	(M.j,M.k);	M.i.normalize	();
                        M.j.crossproduct   	(M.k,M.i);	M.j.normalize  ();
                        if (m_RT_Flags.is(flRT_XFORM)){
                            Fvector p;
                            m_XFORM.transform_tiny(p,m.pos);
	                        M.mulA_43		(m_XFORM);
                            FillSprite		(pv,M.j,M.i,p,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }else{
                            FillSprite		(pv,M.j,M.i,m.pos,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }
                    }else{
						Fvector 			dir;
                        if (speed>=EPS_S)	dir.div	(m.vel,speed);
                        else				dir.setHP(-m_Def->m_APDefaultRotation.y,-m_Def->m_APDefaultRotation.x);
                        if (m_RT_Flags.is(flRT_XFORM)){
                            Fvector p,d;
                            m_XFORM.transform_tiny	(p,m.pos);
                            m_XFORM.transform_dir	(d,dir);
                            FillSprite	(pv,p,d,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }else{
                            FillSprite	(pv,m.pos,dir,lt,rb,r_x,r_y,m.color,m.rot.x);
                        }
                    }
				}else{
					if (m_RT_Flags.is(flRT_XFORM)){
						Fvector p;
						m_XFORM.transform_tiny	(p,m.pos);
						FillSprite	(pv,Device.vCameraTop,Device.vCameraRight,p,lt,rb,r_x,r_y,m.color,m.rot.x);
					}else{
						FillSprite	(pv,Device.vCameraTop,Device.vCameraRight,m.pos,lt,rb,r_x,r_y,m.color,m.rot.x);
					}
				}
			}
			dwCount 			= u32(pv-pv_start);
			RCache.Vertex.Unlock(dwCount,geom->vb_stride);
			if (dwCount)    {
				RCache.set_xform_world	(Fidentity);
				RCache.set_Geometry		(geom);

//              u32 cm					= RCache.get_CullMode();
                RCache.set_CullMode		(m_Def->m_Flags.is(CPEDef::dfCulling)?(m_Def->m_Flags.is(CPEDef::dfCullCCW)?CULL_CCW:CULL_CW):CULL_NONE);
				RCache.Render	   		(D3DPT_TRIANGLELIST,dwOffset,0,dwCount,0,dwCount/2);
                RCache.set_CullMode		(CULL_CCW	); 
			}
		}
	}
}