/// Execute the animation and returns true if the animation is over (can be deleted) bool AnimationCamera::Execute() { bool isAnimationFinished = false; AnimationExecuteWithTime(isAnimationFinished); CameraAnimationFrame result; switch (mAlgo) { case ANIMATION_LINEAR: result[Position()] = CalculateLinear<CameraAnimationFrame,Position>(this); result[Aim()] = CalculateLinear<CameraAnimationFrame,Aim>(this); result[UpVector()] = CalculateLinear<CameraAnimationFrame,UpVector>(this); break; case ANIMATION_BEZIER: result[Position()] = CalculateBezier<CameraAnimationFrame,Position>(this); result[Aim()] = CalculateBezier<CameraAnimationFrame,Aim>(this); result[UpVector()] = CalculateBezier<CameraAnimationFrame,UpVector>(this); break; default: checkf(false, "New algo type not handled by Camera Animations"); break; } mCamera->assignerPosition(result[Position()]); mCamera->assignerPointVise(result[Aim()]); mCamera->assignerDirectionHaut(result[UpVector()]); return isAnimationFinished; }
void Direct3D::UpdateCamera() //Move the 3D camera, not needed in 2D. { D3DXVECTOR3 EyePos(0, 0, 0); D3DXVECTOR3 TargetPos(0, 0, 0); D3DXVECTOR3 UpVector(0, 0, 0); D3DXMATRIXA16 View; D3DXMatrixLookAtLH(&View, &EyePos, &TargetPos, &UpVector); D3DDevice->SetTransform(D3DTS_VIEW, &View); }
void lcLight::UpdatePosition(lcStep Step) { mPosition = CalculateKey(mPositionKeys, Step); mTargetPosition = CalculateKey(mTargetPositionKeys, Step); mAmbientColor = CalculateKey(mAmbientColorKeys, Step); mDiffuseColor = CalculateKey(mDiffuseColorKeys, Step); mSpecularColor = CalculateKey(mSpecularColorKeys, Step); mAttenuation = CalculateKey(mAttenuationKeys, Step); mSpotCutoff = CalculateKey(mSpotCutoffKeys, Step); mSpotExponent = CalculateKey(mSpotExponentKeys, Step); if (IsPointLight()) { mWorldLight = lcMatrix44Identity(); mWorldLight.SetTranslation(-mPosition); } else { lcVector3 FrontVector(mTargetPosition - mPosition); lcVector3 UpVector(1, 1, 1); if (fabs(FrontVector[0]) < fabs(FrontVector[1])) { if (fabs(FrontVector[0]) < fabs(FrontVector[2])) UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); else UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); } else { if (fabs(FrontVector[1]) < fabs(FrontVector[2])) UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); else UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); } mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); } }
// Using swept code & direct position update (no physics engine) // This function is the generic character controller logic, valid for all swept volumes void SweepTest::MoveCharacter( void* user_data, void* user_data2, SweptVolume& volume, const NxVec3& direction, NxU32 nb_boxes, const NxExtendedBounds3* boxes, const void** box_user_data, NxU32 nb_capsules, const NxExtendedCapsule* capsules, const void** capsule_user_data, NxU32 groups, float min_dist, NxU32& collision_flags, const NxGroupsMask* groupsMask, bool constrainedClimbingMode ) { mHitNonWalkable = false; NxU32 CollisionFlags = 0; const NxU32 MaxIter = mMaxIter; // 1 for "collide and stop" const NxU32 MaxIterUp = MaxIter; const NxU32 MaxIterSides = MaxIter; // const NxU32 MaxIterDown = gWalkExperiment ? MaxIter : 1; const NxU32 MaxIterDown = 1; // ### this causes the artificial gap on top of chars float StepOffset = mStepOffset; // Default step offset can be cancelled in some cases. // Save initial height Extended OriginalHeight = volume.mCenter[mUpDirection]; Extended OriginalBottomPoint = OriginalHeight - volume.mHalfHeight; // UBI // TEST! Disable auto-step when flying. Not sure this is really useful. if(direction[mUpDirection]>0.0f) StepOffset = 0.0f; // Decompose motion into 3 independent motions: up, side, down // - if the motion is purely down (gravity only), the up part is needed to fight accuracy issues. For example if the // character is already touching the geometry a bit, the down sweep test might have troubles. If we first move it above // the geometry, the problems disappear. // - if the motion is lateral (character moving forward under normal gravity) the decomposition provides the autostep feature // - if the motion is purely up, the down part can be skipped NxVec3 UpVector(0.0f, 0.0f, 0.0f); NxVec3 DownVector(0.0f, 0.0f, 0.0f); if(direction[mUpDirection]<0.0f) DownVector[mUpDirection] = direction[mUpDirection]; else UpVector[mUpDirection] = direction[mUpDirection]; NxVec3 SideVector = direction; SideVector[mUpDirection] = 0.0f; // If the side motion is zero, i.e. if the character is not really moving, disable auto-step. if(!SideVector.isZero()) UpVector[mUpDirection] += StepOffset; // ==========[ Initial volume query ]=========================== if(1) { NxVec3 MotionExtents = UpVector; MotionExtents.max(SideVector); MotionExtents.max(DownVector); NxExtendedBounds3 TemporalBox; volume.ComputeTemporalBox(*this, TemporalBox, volume.mCenter, MotionExtents); // Gather touched geoms UpdateTouchedGeoms(user_data, volume, nb_boxes, boxes, box_user_data, nb_capsules, capsules, capsule_user_data, groups, TemporalBox, groupsMask); } // ==========[ UP PASS ]=========================== mCachedTriIndexIndex = 0; const bool PerformUpPass = true; NxU32 NbCollisions=0; if(PerformUpPass) { // Prevent user callback for up motion. This up displacement is artificial, and only needed for auto-stepping. // If we call the user for this, we might eventually apply upward forces to objects resting on top of us, even // if we visually don't move. This produces weird-looking motions. mValidateCallback = false; // In the walk-experiment we explicitely want to ban any up motions, to avoid characters climbing slopes they shouldn't climb. // So let's bypass the whole up pass. if(!mWalkExperiment) { // ### MaxIter here seems to "solve" the V bug if(DoSweepTest(user_data, user_data2, nb_boxes, boxes, box_user_data, nb_capsules, capsules, capsule_user_data, volume, UpVector, MaxIterUp, &NbCollisions, groups, min_dist, groupsMask)) { if(NbCollisions) { CollisionFlags |= NXCC_COLLISION_UP; // Clamp step offset to make sure we don't undo more than what we did Extended Delta = volume.mCenter[mUpDirection] - OriginalHeight; if(Delta<StepOffset) { StepOffset=float(Delta); } } } } } // ==========[ SIDE PASS ]=========================== mCachedTriIndexIndex = 1; mValidateCallback = true; const bool PerformSidePass = true; if(PerformSidePass) { NbCollisions=0; if(DoSweepTest(user_data, user_data2, nb_boxes, boxes, box_user_data, nb_capsules, capsules, capsule_user_data, volume, SideVector, MaxIterSides, &NbCollisions, groups, min_dist, groupsMask)) { if(NbCollisions) CollisionFlags |= NXCC_COLLISION_SIDES; } } // ==========[ DOWN PASS ]=========================== mCachedTriIndexIndex = 2; const bool PerformDownPass = true; if(PerformDownPass) { NbCollisions=0; if(!SideVector.isZero()) // We disabled that before so we don't have to undo it in that case DownVector[mUpDirection] -= StepOffset; // Undo our artificial up motion mValidTri = false; // min_dist actually makes a big difference :( // AAARRRGGH: if we get culled because of min_dist here, mValidTri never becomes valid! if(DoSweepTest(user_data, user_data2, nb_boxes, boxes, box_user_data, nb_capsules, capsules, capsule_user_data, volume, DownVector, MaxIterDown, &NbCollisions, groups, min_dist, groupsMask, true)) { if(NbCollisions) { CollisionFlags |= NXCC_COLLISION_DOWN; if(mHandleSlope) // PT: I think the following fix shouldn't be performed when mHandleSlope is false. { // PT: the following code is responsible for a weird capsule behaviour, // when colliding against a highly tesselated terrain: // - with a large direction vector, the capsule gets stuck against some part of the terrain // - with a slower direction vector (but in the same direction!) the capsule manages to move // I will keep that code nonetheless, since it seems to be useful for them. // constrainedClimbingMode if ( constrainedClimbingMode && mContactPointHeight > OriginalBottomPoint + StepOffset) { mHitNonWalkable = true; if(!mWalkExperiment) return; } //~constrainedClimbingMode } } } // TEST: do another down pass if we're on a non-walkable poly // ### kind of works but still not perfect // ### could it be because we zero the Y impulse later? // ### also check clamped response vectors if(mHandleSlope && mValidTri && direction[mUpDirection]<0.0f) { NxVec3 Normal; #ifdef USE_CONTACT_NORMAL_FOR_SLOPE_TEST Normal = mCN; #else mTouched.normal(Normal); #endif // if(fabsf(Normal|NxVec3(0.0f, 1.0f, 0.0f))<cosf(45.0f*DEGTORAD)) if(Normal[mUpDirection]>=0.0f && Normal[mUpDirection]<mSlopeLimit) { mHitNonWalkable = true; // Early exit if we're going to run this again anyway... if(!mWalkExperiment) return; /* CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[0], mTouched.mVerts[1], ARGB_YELLOW); CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[0], mTouched.mVerts[2], ARGB_YELLOW); CatchScene()->GetRenderer()->AddLine(mTouched.mVerts[1], mTouched.mVerts[2], ARGB_YELLOW); */ // ==========[ WALK EXPERIMENT ]=========================== mNormalizeResponse=true; Extended Delta = volume.mCenter[mUpDirection] > OriginalHeight ? volume.mCenter[mUpDirection] - OriginalHeight : 0.0f; Delta += fabsf(direction[mUpDirection]); Extended Recover = Delta; NbCollisions=0; const Extended MD = Recover < min_dist ? Recover/float(MaxIter) : min_dist; NxVec3 RecoverPoint(0,0,0); RecoverPoint[mUpDirection]=-float(Recover); if(DoSweepTest(user_data, user_data2, nb_boxes, boxes, box_user_data, nb_capsules, capsules, capsule_user_data, volume, RecoverPoint, MaxIter, &NbCollisions, groups, float(MD), groupsMask)) { // if(NbCollisions) CollisionFlags |= COLLISION_Y_DOWN; // PT: why did we do this ? Removed for now. It creates a bug (non registered event) when we land on a steep poly. // However this might have been needed when we were sliding on those polygons, and we didn't want the land anim to // start while we were sliding. // if(NbCollisions) CollisionFlags &= ~NXCC_COLLISION_DOWN; } mNormalizeResponse=false; } } } // Setup new collision flags collision_flags = CollisionFlags; }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_DrawFrustumSceneProxy_DrawDynamicElements ); FVector Direction(1,0,0); FVector LeftVector(0,1,0); FVector UpVector(0,0,1); FVector Verts[8]; // FOVAngle controls the horizontal angle. const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f); float HozLength = 0.0f; float VertLength = 0.0f; if (FrustumAngle > 0.0f) { HozLength = FrustumStartDist * FMath::Tan(HozHalfAngleInRadians); VertLength = HozLength / FrustumAspectRatio; } else { const float OrthoWidth = (FrustumAngle == 0.0f) ? 1000.0f : -FrustumAngle; HozLength = OrthoWidth * 0.5f; VertLength = HozLength / FrustumAspectRatio; } // near plane verts Verts[0] = (Direction * FrustumStartDist) + (UpVector * VertLength) + (LeftVector * HozLength); Verts[1] = (Direction * FrustumStartDist) + (UpVector * VertLength) - (LeftVector * HozLength); Verts[2] = (Direction * FrustumStartDist) - (UpVector * VertLength) - (LeftVector * HozLength); Verts[3] = (Direction * FrustumStartDist) - (UpVector * VertLength) + (LeftVector * HozLength); if (FrustumAngle > 0.0f) { HozLength = FrustumEndDist * FMath::Tan(HozHalfAngleInRadians); VertLength = HozLength / FrustumAspectRatio; } // far plane verts Verts[4] = (Direction * FrustumEndDist) + (UpVector * VertLength) + (LeftVector * HozLength); Verts[5] = (Direction * FrustumEndDist) + (UpVector * VertLength) - (LeftVector * HozLength); Verts[6] = (Direction * FrustumEndDist) - (UpVector * VertLength) - (LeftVector * HozLength); Verts[7] = (Direction * FrustumEndDist) - (UpVector * VertLength) + (LeftVector * HozLength); for (int32 X = 0; X < 8; ++X) { Verts[X] = GetLocalToWorld().TransformPosition(Verts[X]); } for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); const FSceneView* View = Views[ViewIndex]; const uint8 DepthPriorityGroup = GetDepthPriorityGroup(View); PDI->DrawLine( Verts[0], Verts[1], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[1], Verts[2], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[2], Verts[3], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[3], Verts[0], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[4], Verts[5], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[5], Verts[6], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[6], Verts[7], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[7], Verts[4], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[0], Verts[4], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[1], Verts[5], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[2], Verts[6], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[3], Verts[7], FrustumColor, DepthPriorityGroup ); } } }
//! OnAnimate() is called just before rendering the whole scene. //! nodes may calculate or store animations here, and may do other useful things, //! dependent on what they are. void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { //Alt + LM = Rotate around camera pivot //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) if (node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); if (OldCamera != camera) { OldTarget = camera->getTarget(); OldCamera = camera; } Target = camera->getTarget(); const SViewFrustum* va = camera->getViewFrustum(); f32 nRotX = RotX; f32 nRotY = RotY; f32 nZoom = CurrentZoom; if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) { if (!Zooming) { ZoomStartX = MousePos.X; ZoomStartY = MousePos.Y; Zooming = true; nZoom = CurrentZoom; } else { f32 old = nZoom; nZoom += (ZoomStartX - MousePos.X) * ZoomSpeed; f32 targetMinDistance = 0.1f; if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close nZoom = targetMinDistance; if (nZoom < 0) nZoom = old; } } else { if (Zooming) { f32 old = CurrentZoom; CurrentZoom = CurrentZoom + (ZoomStartX - MousePos.X ) * ZoomSpeed; nZoom = CurrentZoom; if (nZoom < 0) nZoom = CurrentZoom = old; } Zooming = false; } // Translation --------------------------------- core::vector3df translate(OldTarget), UpVector(camera->getUpVector()); core::vector3df tvectX = Pos - Target; tvectX = tvectX.crossProduct(UpVector); tvectX.normalize(); core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown()); tvectY = tvectY.crossProduct(UpVector.Y > 0 ? Pos - Target : Target - Pos); tvectY.normalize(); if (isMouseKeyDown(2) && !Zooming) { if (!Translating) { TranslateStartX = MousePos.X; TranslateStartY = MousePos.Y; Translating = true; } else { translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; } } else { if (Translating) { translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; OldTarget = translate; } Translating = false; } // Rotation ------------------------------------ if (isMouseKeyDown(0) && !Zooming) { if (!Rotating) { RotateStartX = MousePos.X; RotateStartY = MousePos.Y; Rotating = true; nRotX = RotX; nRotY = RotY; } else { nRotX += (RotateStartX - MousePos.X) * RotateSpeed; nRotY += (RotateStartY - MousePos.Y) * RotateSpeed; } } else { if (Rotating) { RotX = RotX + (RotateStartX - MousePos.X) * RotateSpeed; RotY = RotY + (RotateStartY - MousePos.Y) * RotateSpeed; nRotX = RotX; nRotY = RotY; } Rotating = false; } // Set Pos ------------------------------------ Target = translate; Pos.X = nZoom + Target.X; Pos.Y = Target.Y; Pos.Z = Target.Z; Pos.rotateXYBy(nRotY, Target); Pos.rotateXZBy(-nRotX, Target); // Rotation Error ---------------------------- // jox: fixed bug: jitter when rotating to the top and bottom of y UpVector.set(0,1,0); UpVector.rotateXYBy(-nRotY); UpVector.rotateXZBy(-nRotX+180.f); camera->setPosition(Pos); camera->setTarget(Target); camera->setUpVector(UpVector); }
void lcLight::DrawSpotLight(lcContext* Context, const lcMatrix44& ViewMatrix) const { lcVector3 FrontVector(mTargetPosition - mPosition); lcVector3 UpVector(1, 1, 1); if (fabs(FrontVector[0]) < fabs(FrontVector[1])) { if (fabs(FrontVector[0]) < fabs(FrontVector[2])) UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); else UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); } else { if (fabs(FrontVector[1]) < fabs(FrontVector[2])) UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); else UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); } lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); LightMatrix = lcMatrix44AffineInverse(LightMatrix); LightMatrix.SetTranslation(lcVector3(0, 0, 0)); lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMul(lcMatrix44Translation(mPosition), ViewMatrix)); Context->SetWorldViewMatrix(LightViewMatrix); float Verts[(20 + 8 + 2 + 16) * 3]; float* CurVert = Verts; for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) { float c = cosf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; float s = sinf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; *CurVert++ = c; *CurVert++ = s; *CurVert++ = LC_LIGHT_POSITION_EDGE; *CurVert++ = c; *CurVert++ = s; *CurVert++ = -LC_LIGHT_POSITION_EDGE; } *CurVert++ = -12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; *CurVert++ = 12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; *CurVert++ = 12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; *CurVert++ = -12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; float Length = FrontVector.Length(); *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; const GLushort Indices[56 + 24 + 2 + 40] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, 16, 17, 17, 18, 18, 19, 19, 16, 20, 21, 21, 22, 22, 23, 23, 20, 24, 25, 25, 26, 26, 27, 27, 24, 20, 24, 21, 25, 22, 26, 23, 27, 28, 29, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, 28, 30, 28, 34, 28, 38, 28, 42 }; Context->SetVertexBufferPointer(Verts); Context->SetVertexFormat(0, 3, 0, 0); float LineWidth = lcGetPreferences().mLineWidth; if (!IsSelected()) { Context->SetLineWidth(LineWidth); lcSetColorLight(); glDrawElements(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, Indices); } else { if (IsSelected(LC_LIGHT_SECTION_POSITION)) { Context->SetLineWidth(2.0f * LineWidth); if (IsFocused(LC_LIGHT_SECTION_POSITION)) lcSetColorFocused(); else lcSetColorSelected(); } else { Context->SetLineWidth(LineWidth); lcSetColorLight(); } glDrawElements(GL_LINES, 56, GL_UNSIGNED_SHORT, Indices); if (IsSelected(LC_LIGHT_SECTION_TARGET)) { Context->SetLineWidth(2.0f * LineWidth); if (IsFocused(LC_LIGHT_SECTION_TARGET)) lcSetColorFocused(); else lcSetColorSelected(); } else { Context->SetLineWidth(LineWidth); lcSetColorLight(); } glDrawElements(GL_LINES, 24, GL_UNSIGNED_SHORT, Indices + 56); Context->SetLineWidth(LineWidth); lcSetColorLight(); float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) { *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; *CurVert++ = -Length; } glDrawElements(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, Indices + 56 + 24); } Context->ClearVertexBuffer(); // context remove }