bool eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { auto ev = static_cast<QMouseEvent*>(event); if (ev->button() == Qt::RightButton) { auto buttons = ev->buttons(); if (buttons & Qt::RightButton) { buttons ^= Qt::RightButton; buttons |= Qt::LeftButton; } QMouseEvent lev{ev->type(), ev->localPos(), ev->windowPos(), ev->screenPos(), Qt::LeftButton, buttons, ev->modifiers(), ev->source()}; Q_ASSERT(! (lev.buttons() & Qt::RightButton)); QCoreApplication::sendEvent(watched, &lev); return true; } } return QObject::eventFilter(watched, event); }
void Root::render() { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); if(scene) { scene->render(); for(std::list<FrameListener*>::iterator it = frameListeners.begin(); it != frameListeners.end();++it) (*it)->onRender(); GLfloat depth; glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); vec4 screenPos(2.0f * mouseX /((float)windowWidth) - 1.0f, 2.0f * mouseY/((float)windowHeight) - 1.0f, 2.0f*depth-1.0f, 1.0); screenPos = scene->getCamera()->getInverseVPMatrix() * screenPos; screenPos /= screenPos.w; clickScreenLocation.x = screenPos.x; clickScreenLocation.y = screenPos.y; clickScreenLocation.z = screenPos.z; } if(overlay) overlay->render(); glfwSwapBuffers(); }
/**\brief Handles Hud related User Input * \param events User entered Keyboard and mouse clicks */ void Hud::HandleInput( list<InputEvent> & events, Camera* camera, SpriteManager* sprites ) { list<InputEvent>::iterator i; for(i = events.begin(); i != events.end() ; ++i ) { // Mouse Clicks if( i->type == MOUSE && i->mstate==MOUSELDOWN) { if( (i->mx > Video::GetWidth() - 129) && (i->my < Image::Get( "data/skin/hud_radarnav.png" )->GetHeight() + 5) ) { //Radar::StartLargeMode(camera, sprites); } else { Coordinate screenPos(i->mx, i->my), worldPos; camera->TranslateScreenToWorld( screenPos, worldPos ); // Target any clicked Sprite list<Sprite*> *impacts = sprites->GetSpritesNear( worldPos, 5 ); if( impacts->size() > 0) { Target( (*(impacts->begin()))->GetID()); } delete impacts; } } } }
void CanvasQt::wheelEvent(QWheelEvent* e){ MouseEvent::MouseWheelOrientation orientation; if (e->orientation() == Qt::Horizontal) { orientation = MouseEvent::MOUSE_WHEEL_HORIZONTAL; } else { orientation = MouseEvent::MOUSE_WHEEL_VERTICAL; } #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) QPoint numPixels = e->pixelDelta(); QPoint numDegrees = e->angleDelta() / 8 / 15; #else QPoint numPixels; QPoint numDegrees = QPoint(0, e->delta() / 8 / 15); #endif int numSteps = 0; if (!numPixels.isNull()) { numSteps = (orientation==MouseEvent::MOUSE_WHEEL_HORIZONTAL? numPixels.x() : numPixels.y()) / 5; } else if (!numDegrees.isNull()) { numSteps = (orientation==MouseEvent::MOUSE_WHEEL_HORIZONTAL? numDegrees.x() : numDegrees.y()); } ivec2 screenPos(e->pos().x(), e->pos().y()); ivec2 screenPosInvY(screenPos.x, static_cast<int>(getScreenDimensions().y) - 1 - screenPos.y); MouseEvent mouseEvent(screenPos, numSteps, EventConverterQt::getMouseWheelButton(e), MouseEvent::MOUSE_STATE_WHEEL, orientation, EventConverterQt::getModifier(e), getScreenDimensions(), getDepthValueAtCoord(screenPosInvY)); e->accept(); Canvas::mouseWheelEvent(&mouseEvent); }
void InputPreview::setRulerPos(QPointF const& _eventPos) { if (!input()) return; QPointF _pos = screenPos(_eventPos); input()->setRulerPos(_pos); emit inputChanged(); }
void TestInputPreview::setRulerPos(QPointF const& _eventPos) { if (!input()) return; QPointF _pos = screenPos(_eventPos); static_cast<input::TestImage*>(input())->setRulerPos(_pos); input()->update(); triggerUpdate(); emit inputChanged(); }
glm::vec3 Camera::screenPositionToDirection(float x, float y) const { int width = 0, height = 0; glfwGetWindowSize(glfwGetCurrentContext(), &width, &height); glm::vec3 screenPos(x / width * 2 - 1, (y / height * 2 - 1) * -1, -1); screenPos.x /= m_projection[0][0]; screenPos.y /= m_projection[1][1]; return glm::normalize(m_transform * glm::vec4(screenPos, 0)).xyz(); }
void PlayerControl::pickRayDirection() { double x = 0; double y = 0; glfwGetCursorPos(m_window, &x, &y); glm::vec3 screenPos(x / DEFAULT_SCREENWIDTH * 2 - 1, (y / DEFAULT_SCREENHEIGHT * 2 - 1) * -1, -1); screenPos.x /= m_projectionMatrix[0][0]; screenPos.y /= m_projectionMatrix[1][1]; m_rayDir = glm::normalize(m_cameraMatrix * glm::vec4(screenPos, 0)).xyz(); }
void CanvasQt::mousePressEvent(QMouseEvent* e) { #if !defined(QT_NO_GESTURES) && defined(USING_QT4) if (gestureMode_) return; #endif ivec2 screenPos(e->pos().x(), e->pos().y()); ivec2 screenPosInvY(screenPos.x, static_cast<int>(getScreenDimensions().y) - 1 - screenPos.y); MouseEvent mouseEvent(screenPos, EventConverterQt::getMouseButton(e), MouseEvent::MOUSE_STATE_PRESS, EventConverterQt::getModifier(e), getScreenDimensions(), getDepthValueAtCoord(screenPosInvY)); e->accept(); Canvas::mousePressEvent(&mouseEvent); }
void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight) { // If alpha is 0, nothing will be rendered, so do not add the quad if (!(color_ & 0xff000000)) return; //const IntVector2& screenPos = element_->GetScreenPosition(); IntVector2 screenPos(0, 0); float left = (float)(x + screenPos.x_) - posAdjust; float right = left + (float)width; float top = (float)(y + screenPos.y_) - posAdjust; float bottom = top + (float)height; float leftUV = texOffsetX * invTextureSize_.x_; float topUV = texOffsetY * invTextureSize_.y_; float rightUV = (texOffsetX + (texWidth ? texWidth : width)) * invTextureSize_.x_; float bottomUV = (texOffsetY + (texHeight ? texHeight : height)) * invTextureSize_.y_; unsigned begin = vertexData_->Size(); vertexData_->Resize(begin + 6 * UI_VERTEX_SIZE); float* dest = &(vertexData_->At(begin)); vertexEnd_ = vertexData_->Size(); dest[0] = left; dest[1] = top; dest[2] = 0.0f; ((unsigned&)dest[3]) = color_; dest[4] = leftUV; dest[5] = topUV; dest[6] = right; dest[7] = top; dest[8] = 0.0f; ((unsigned&)dest[9]) = color_; dest[10] = rightUV; dest[11] = topUV; dest[12] = left; dest[13] = bottom; dest[14] = 0.0f; ((unsigned&)dest[15]) = color_; dest[16] = leftUV; dest[17] = bottomUV; dest[18] = right; dest[19] = top; dest[20] = 0.0f; ((unsigned&)dest[21]) = color_; dest[22] = rightUV; dest[23] = topUV; dest[24] = right; dest[25] = bottom; dest[26] = 0.0f; ((unsigned&)dest[27]) = color_; dest[28] = rightUV; dest[29] = bottomUV; dest[30] = left; dest[31] = bottom; dest[32] = 0.0f; ((unsigned&)dest[33]) = color_; dest[34] = leftUV; dest[35] = bottomUV; dest += 36; }
void CanvasQt::mouseReleaseEvent(QMouseEvent* e) { #if !defined(QT_NO_GESTURES) && defined(USING_QT4) if (gestureMode_){ gestureMode_ = false; return; } #endif uvec2 screenPos(static_cast<unsigned int>(e->pos().x()), static_cast<unsigned int>(e->pos().y())); MouseEvent mouseEvent(screenPos, EventConverterQt::getMouseButtonCausingEvent(e), MouseEvent::MOUSE_STATE_RELEASE, EventConverterQt::getModifier(e), getScreenDimensions(), getDepthValueAtCoord(screenPos)); e->accept(); Canvas::mouseReleaseEvent(&mouseEvent); }
glm::vec3 Camera::pickAgainstPlane(float x, float y, const glm::vec4& plane) const { int width = 0, height = 0; glfwGetWindowSize(glfwGetCurrentContext(), &width, &height); glm::vec3 screenPos(x / width * 2 - 1, (y / height * 2 - 1) * -1, -1); screenPos.x /= m_projection[0][0]; screenPos.y /= m_projection[1][1]; glm::vec3 dir = glm::normalize(m_transform * glm::vec4(screenPos, 0)).xyz(); float d = (plane.w - glm::dot(m_transform[3].xyz(), plane.xyz()) / glm::dot(dir, plane.xyz())); return m_transform[3].xyz() + dir * d; }
/**\brief Handles Hud related User Input * \param events User entered Keyboard and mouse clicks */ void Hud::HandleInput( list<InputEvent> & events ) { list<InputEvent>::iterator i; for(i= events.begin(); i != events.end() ; ++i ) { // Mouse Clicks if( i->type == MOUSE && i->mstate==MOUSELDOWN) { Coordinate screenPos(i->mx, i->my), worldPos; Camera::Instance()->TranslateScreenToWorld( screenPos, worldPos ); // Target any clicked Sprite list<Sprite*> *impacts = SpriteManager::Instance()->GetSpritesNear( worldPos, 5 ); if( impacts->size() > 0) { Target( (*(impacts->begin()))->GetID()); } delete impacts; } } }
void CanvasGLFW::mouseMotion(GLFWwindow* window, double x, double y) { CanvasGLFW* thisCanvas = getCanvasGLFW(window); ivec2 screenPos(floor(x), floor(y)); ivec2 screenPosInvY(screenPos.x, static_cast<int>(thisCanvas->getScreenDimensions().y) - 1 - screenPos.y); MouseEvent::MouseState state = (thisCanvas->mouseState_ == MouseEvent::MOUSE_STATE_PRESS ? MouseEvent::MOUSE_STATE_MOVE : thisCanvas->mouseState_); MouseEvent mouseEvent(screenPos, thisCanvas->mouseButton_, state, thisCanvas->mouseModifiers_, thisCanvas->getScreenDimensions(), thisCanvas->getDepthValueAtCoord(screenPosInvY)); if (state == MouseEvent::MOUSE_STATE_MOVE) thisCanvas->mouseMoveEvent(&mouseEvent); else if (state == MouseEvent::MOUSE_STATE_RELEASE) thisCanvas->mouseReleaseEvent(&mouseEvent); }
void CanvasGLFW::scroll(GLFWwindow* window, double xoffset, double yoffset) { CanvasGLFW* thisCanvas = getCanvasGLFW(window); thisCanvas->mouseButton_ = MouseEvent::MOUSE_BUTTON_MIDDLE; thisCanvas->mouseState_ = MouseEvent::MOUSE_STATE_WHEEL; thisCanvas->mouseModifiers_ = KeyboardEvent::MODIFIER_NONE; double x; double y; glfwGetCursorPos(window, &x, &y); ivec2 screenPos(floor(x), floor(y)); ivec2 screenPosInvY(screenPos.x, static_cast<int>(thisCanvas->getScreenDimensions().y) - 1 - screenPos.y); int delta = static_cast<int>(yoffset < 0.0 ? floor(yoffset) : ceil(yoffset)); MouseEvent mouseEvent(screenPos, delta, thisCanvas->mouseButton_, thisCanvas->mouseState_, MouseEvent::MOUSE_WHEEL_VERTICAL, thisCanvas->mouseModifiers_, thisCanvas->getScreenDimensions(), thisCanvas->getDepthValueAtCoord(screenPosInvY)); thisCanvas->mouseWheelEvent(&mouseEvent); }
void CanvasGLFW::mouseButton(GLFWwindow* window, int button, int action, int mods) { CanvasGLFW* thisCanvas = getCanvasGLFW(window); thisCanvas->mouseButton_ = mapMouseButton(button); thisCanvas->mouseState_ = mapMouseState(action); thisCanvas->mouseModifiers_ = mapModifiers(mods); double x; double y; glfwGetCursorPos(window, &x, &y); ivec2 screenPos(floor(x), floor(y)); ivec2 screenPosInvY(screenPos.x, static_cast<int>(thisCanvas->getScreenDimensions().y) - 1 - screenPos.y); MouseEvent mouseEvent(screenPos, thisCanvas->mouseButton_, thisCanvas->mouseState_, thisCanvas->mouseModifiers_, thisCanvas->getScreenDimensions(), thisCanvas->getDepthValueAtCoord(screenPosInvY)); if (thisCanvas->mouseState_ == MouseEvent::MOUSE_STATE_PRESS) thisCanvas->mousePressEvent(&mouseEvent); else if (thisCanvas->mouseState_ == MouseEvent::MOUSE_STATE_RELEASE) thisCanvas->mouseReleaseEvent(&mouseEvent); }
glm::vec3 Camera::PickAgainstPlane(float x, float y, const glm::vec4& _plane) { int width = 0; int height = 0; glfwGetWindowSize(glfwGetCurrentContext(), &width, &height); glm::vec3 screenPos(x / width * 2 - 1, (y / height * 2 - 1) * -1, -1); screenPos.x /= m_projectionTransform[0][0]; screenPos.y /= m_projectionTransform[1][1]; glm::vec3 dir = glm::normalize(m_worldTransform * glm::vec4(screenPos, 0)).xyz(); float d = (_plane.w - glm::dot(m_worldTransform[3].xyz(), _plane.xyz()) / glm::dot(dir, _plane.xyz())); if (d >= 0) { return m_worldTransform[3].xyz() + dir * d; } else { return glm::vec3(0); } }
void CanvasQt::mouseMoveEvent(QMouseEvent* e) { #if !defined(QT_NO_GESTURES) if (gestureMode_) return; #endif ivec2 screenPos(e->pos().x(), e->pos().y()); ivec2 screenPosInvY(screenPos.x, static_cast<int>(getScreenDimensions().y) - 1 - screenPos.y); // Optimization, do not sample depth value when hovering, i.e. move without holding a mouse button int button = EventConverterQt::getMouseButton(e); double depth = 1.0; if (button != MouseEvent::MOUSE_BUTTON_NONE) depth = getDepthValueAtCoord(screenPosInvY); MouseEvent mouseEvent(screenPos, button, MouseEvent::MOUSE_STATE_MOVE, EventConverterQt::getModifier(e), getScreenDimensions(), depth); e->accept(); Canvas::mouseMoveEvent(&mouseEvent); }
void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) { if ( !isFirstResponder() ) setFirstResponder(); // Get the clicked terrain position. Point3F tPos; if ( !getTerrainPos( event, tPos ) ) return; mouseLock(); // Find any road / node at the clicked position. // TODO: handle overlapping roads/nodes somehow, cycle through them. DecalRoad *roadPtr = NULL; S32 closestNodeIdx = -1; F32 closestDist = F32_MAX; DecalRoad *closestNodeRoad = NULL; // First, find the closest node in any road to the clicked position. for ( SimSetIterator iter(mRoadSet); *iter; ++iter ) { roadPtr = static_cast<DecalRoad*>( *iter ); U32 idx; if ( roadPtr->getClosestNode( tPos, idx ) ) { Point3F nodePos = roadPtr->getNodePosition(idx); F32 dist = ( nodePos - tPos ).len(); if ( dist < closestDist ) { closestNodeIdx = idx; closestDist = dist; closestNodeRoad = roadPtr; } } } // // Second, determine if the screen-space node rectangle // contains the clicked position. bool nodeClicked = false; S32 clickedNodeIdx = -1; if ( closestNodeIdx != -1 ) { Point3F nodePos = closestNodeRoad->getNodePosition( closestNodeIdx ); Point3F temp; project( nodePos, &temp ); Point2I screenPos( temp.x, temp.y ); RectI nodeRect( screenPos - mNodeHalfSize, mNodeHalfSize * 2 ); nodeClicked = nodeRect.pointInRect( event.mousePoint ); if ( nodeClicked ) clickedNodeIdx = closestNodeIdx; } // // Determine the clickedRoad // DecalRoad *clickedRoadPtr = NULL; U32 insertNodeIdx = 0; if ( nodeClicked && (mSelRoad == NULL || closestNodeRoad == mSelRoad) ) { // If a node was clicked, the owning road is always // considered the clicked road. clickedRoadPtr = closestNodeRoad; } else { // check the selected road first if ( mSelRoad != NULL && mSelRoad->containsPoint( tPos, &insertNodeIdx ) ) { clickedRoadPtr = mSelRoad; nodeClicked = false; clickedNodeIdx = -1; } else { // Otherwise, we must ask each road if it contains // the clicked pos. for ( SimSetIterator iter(mRoadSet); *iter; ++iter ) { roadPtr = static_cast<DecalRoad*>( *iter ); if ( roadPtr->containsPoint( tPos, &insertNodeIdx ) ) { clickedRoadPtr = roadPtr; break; } } } } // shortcuts bool dblClick = ( event.mouseClickCount > 1 ); if( dblClick ) { if( mMode == mSelectRoadMode ) { setMode( mAddRoadMode, true ); return; } if( mMode == mAddNodeMode ) { // Delete the node attached to the cursor. deleteSelectedNode(); mMode = mAddRoadMode; return; } } //this check is here in order to bounce back from deleting a whole road with ctrl+z //this check places the editor back into addroadmode if ( mMode == mAddNodeMode ) { if ( !mSelRoad ) mMode = mAddRoadMode; } if ( mMode == mSelectRoadMode ) { // Did not click on a road or a node. if ( !clickedRoadPtr ) { setSelectedRoad( NULL ); setSelectedNode( -1 ); return; } // Clicked on a road that wasn't the currently selected road. if ( clickedRoadPtr != mSelRoad ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( -1 ); return; } // Clicked on a node in the currently selected road that wasn't // the currently selected node. if ( nodeClicked ) { setSelectedNode( clickedNodeIdx ); return; } // Clicked a position on the currently selected road // that did not contain a node. //U32 newNode = clickedRoadPtr->insertNode( tPos, mDefaultWidth, insertNodeIdx ); //setSelectedNode( newNode ); } else if ( mMode == mAddRoadMode ) { if ( nodeClicked && clickedRoadPtr ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx ); mIsDirty = true; return; } else if ( clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; mSelNode = mSelRoad->addNode( tPos, mDefaultWidth ); mIsDirty = true; setSelectedNode( mSelNode ); return; } } DecalRoad *newRoad = new DecalRoad; newRoad->mMaterialName = mMaterialName; newRoad->registerObject(); // Add to MissionGroup SimGroup *missionGroup; if ( !Sim::findObject( "MissionGroup", missionGroup ) ) Con::errorf( "GuiDecalRoadEditorCtrl - could not find MissionGroup to add new DecalRoad" ); else missionGroup->addObject( newRoad ); newRoad->insertNode( tPos, mDefaultWidth, 0 ); U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 ); // Always add to the end of the road, the first node is the start. mAddNodeIdx = U32_MAX; setSelectedRoad( newRoad ); setSelectedNode( newNode ); mMode = mAddNodeMode; // Disable the hover node while in addNodeMode, we // don't want some random node enlarged. mHoverNode = -1; // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. MECreateUndoAction *action = new MECreateUndoAction("Create Road"); action->addObject( newRoad ); // Submit it. undoMan->addAction( action ); //send a callback to script after were done here if one exists if ( isMethod( "onRoadCreation" ) ) Con::executef( this, "onRoadCreation" ); return; } else if ( mMode == mAddNodeMode ) { // Oops the road got deleted, maybe from an undo action? // Back to NormalMode. if ( mSelRoad ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { submitUndo( "Add Node" ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx ); mIsDirty = true; setSelectedNode( mSelNode ); return; } else { if( clickedRoadPtr && clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 ) { submitUndo( "Add Node" ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; mSelNode = mSelRoad->addNode( tPos, mDefaultWidth ); mIsDirty = true; setSelectedNode( mSelNode ); return; } else { submitUndo( "Insert Node" ); // A single-click on empty space while in // AddNode mode means insert / add a node. //submitUndo( "Add Node" ); //F32 width = mSelRoad->getNodeWidth( mSelNode ); U32 newNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx); mIsDirty = true; setSelectedNode( newNode ); return; } } } } else if ( mMode == mInsertPointMode && mSelRoad != NULL) { if ( clickedRoadPtr == mSelRoad ) { F32 w0 = mSelRoad->getNodeWidth( insertNodeIdx ); F32 w1 = mSelRoad->getNodeWidth( insertNodeIdx + 1 ); F32 width = ( w0 + w1 ) * 0.5f; submitUndo( "Insert Node" ); U32 newNode = mSelRoad->insertNode( tPos, width, insertNodeIdx + 1); mIsDirty = true; setSelectedNode( newNode ); return; } } else if ( mMode == mRemovePointMode && mSelRoad != NULL) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); deleteSelectedNode(); return; } } else if ( mMode == mMovePointMode ) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); return; } } else if ( mMode == mScalePointMode ) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); return; } } }
//--------------------------------------------------------------------------- void Terrain::geometry (void) { //--------------------------------------------------------------------- leastZ = 1.0f;leastW = 1.0f; mostZ = -1.0f; mostW = -1.0; leastWY = 0.0f; mostWY = 0.0f; //----------------------------------- // Transform entire list of vertices VertexPtr currentVertex = vertexList; Stuff::Vector3D cameraPos; cameraPos.x = -eye->getCameraOrigin().x; cameraPos.y = eye->getCameraOrigin().z; cameraPos.z = eye->getCameraOrigin().y; float vClipConstant = eye->verticalSphereClipConstant; float hClipConstant = eye->horizontalSphereClipConstant; long i=0; for (i=0;i<numberVertices;i++) { //---------------------------------------------------------------------------------------- // Figure out if we are in front of camera or not. Should be faster then actual project! // Should weed out VAST overwhelming majority of vertices! bool onScreen = false; //----------------------------------------------------------------- // Find angle between lookVector of Camera and vector from camPos // to Target. If angle is less then halfFOV, object is visible. if (eye->usePerspective) { //------------------------------------------------------------------- //NEW METHOD from the WAY BACK Days onScreen = true; Stuff::Vector3D vPosition; vPosition.x = currentVertex->vx; vPosition.y = currentVertex->vy; vPosition.z = currentVertex->pVertex->elevation; Stuff::Vector3D objectCenter; objectCenter.Subtract(vPosition,cameraPos); Camera::cameraFrame.trans_to_frame(objectCenter); float distanceToEye = objectCenter.GetApproximateLength(); Stuff::Vector3D clipVector = objectCenter; clipVector.z = 0.0f; float distanceToClip = clipVector.GetApproximateLength(); float clip_distance = fabs(1.0f / objectCenter.y); if (distanceToClip > CLIP_THRESHOLD_DISTANCE) { //Is vertex on Screen OR close enough to screen that its triangle MAY be visible? // WE have removed the atans here by simply taking the tan of the angle we want above. float object_angle = fabs(objectCenter.z) * clip_distance; float extent_angle = VERTEX_EXTENT_RADIUS / distanceToEye; if (object_angle > (vClipConstant + extent_angle)) { //In theory, we would return here. Object is NOT on screen. onScreen = false; } else { object_angle = fabs(objectCenter.x) * clip_distance; if (object_angle > (hClipConstant + extent_angle)) { //In theory, we would return here. Object is NOT on screen. onScreen = false; } } } if (onScreen) { if (distanceToEye > Camera::MaxClipDistance) { currentVertex->hazeFactor = 1.0f; } else if (distanceToEye > Camera::MinHazeDistance) { currentVertex->hazeFactor = (distanceToEye - Camera::MinHazeDistance) * Camera::DistanceFactor; } else { currentVertex->hazeFactor = 0.0f; } //--------------------------------------- // Vertex is at edge of world or beyond. Stuff::Vector3D vPos(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation); bool isVisible = Terrain::IsGameSelectTerrainPosition(vPos) || drawTerrainGrid; if (!isVisible) { currentVertex->hazeFactor = 1.0f; onScreen = true; } } else { currentVertex->hazeFactor = 1.0f; } } else { currentVertex->hazeFactor = 0.0f; onScreen = true; } bool inView = false; Stuff::Vector4D screenPos(-10000.0f,-10000.0f,-10000.0f,-10000.0f); if (onScreen) { Stuff::Vector3D vertex3D(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation); inView = eye->projectZ(vertex3D,screenPos); currentVertex->px = screenPos.x; currentVertex->py = screenPos.y; currentVertex->pz = screenPos.z; currentVertex->pw = screenPos.w; //---------------------------------------------------------------------------------- //We must transform these but should NOT draw any face where all three are fogged. // if (currentVertex->hazeFactor == 1.0f) // onScreen = false; } else { currentVertex->px = currentVertex->py = 10000.0f; currentVertex->pz = -0.5f; currentVertex->pw = 0.5f; currentVertex->hazeFactor = 0.0f; } //------------------------------------------------------------ // Fix clip. Vertices can all be off screen and triangle // still needs to be drawn! if (eye->usePerspective && Environment.Renderer != 3) { currentVertex->clipInfo = onScreen; } else currentVertex->clipInfo = inView; if (currentVertex->clipInfo) //ONLY set TRUE ones. Otherwise we just reset the FLAG each vertex! { setObjBlockActive(currentVertex->getBlockNumber(), true); setObjVertexActive(currentVertex->vertexNum,true); if (inView) { if (screenPos.z < leastZ) { leastZ = screenPos.z; } if (screenPos.z > mostZ) { mostZ = screenPos.z; } if (screenPos.w < leastW) { leastW = screenPos.w; leastWY = screenPos.y; } if (screenPos.w > mostW) { mostW = screenPos.w; mostWY = screenPos.y; } } } currentVertex++; } //----------------------------------- // setup terrain quad textures // Also sets up mine data. TerrainQuadPtr currentQuad = quadList; for (i=0;i<numberQuads;i++) { currentQuad->setupTextures(); currentQuad++; } float ywRange = 0.0f, yzRange = 0.0f; if (fabs(mostWY - leastWY) > Stuff::SMALL) { ywRange = (mostW - leastW) / (mostWY - leastWY); yzRange = (mostZ - leastZ) / (mostWY - leastWY); } eye->setInverseProject(mostZ,leastW,yzRange,ywRange); //----------------------------------- // update the cloud layer if (Terrain::cloudLayer) Terrain::cloudLayer->update(); }
void CPersistantDebug::UpdateTags(float frameTime, SObj& obj, bool doFirstPass) { if (!doFirstPass) { // Every update calls itself recursively first to calculate the widths of each column // for multicolumn mode. Not the prettiest thing, but it's the best idea I've got so far! UpdateTags(frameTime, obj, true); frameTime = 0.f; for (int i=0; i<obj.columns.size(); ++i) obj.columns[i].height = 0.f; } IFFont *pFont = gEnv->pCryFont->GetFont("default"); assert(pFont); STextDrawContext ctx; ctx.SetSizeIn800x600(false); ctx.SetProportional(true); for (TListTag::iterator iterList = obj.tags.begin(); iterList != obj.tags.end(); ++iterList) { if (iterList->vScreenPos.IsZero()) continue; float tagMaxDist = iterList->params.viewDistance; float fontSize = iterList->params.size * m_pETFontSizeMultiplier->GetFVal(); // Calculate size of text on screen (so we can place it properly) ctx.SetSize(Vec2(12*fontSize, 12*fontSize)); Vec2 textBoxSize = pFont->GetTextSize(iterList->params.text.c_str(), true, ctx); if (doFirstPass) { int pos(iterList->params.column - 1); obj.columns[pos].width = max(obj.columns[pos].width, textBoxSize.x + 15.f); } else { // Determine position SColumn &column = obj.columns[iterList->params.column - 1]; Vec3 screenPos(iterList->vScreenPos); screenPos.x = screenPos.x*0.01f*gEnv->pRenderer->GetWidth(); screenPos.y = screenPos.y*0.01f*gEnv->pRenderer->GetHeight() - textBoxSize.y - column.height; column.height += textBoxSize.y; // Adjust X value for multi-columns if (obj.columns.size() > 1) { int centerLine = obj.columns.size() / 2; if (iterList->params.column <= centerLine) for (int i=iterList->params.column-1; i<centerLine; ++i) screenPos.x -= obj.columns[i].width; else for (int i=centerLine; i<iterList->params.column-1; ++i) screenPos.x += obj.columns[i].width; if (obj.columns.size() % 2 != 0) screenPos.x -= textBoxSize.x*0.5f; } else { screenPos.x -= textBoxSize.x*0.5f; } // Determine color ColorF clr = iterList->params.color; if (1==m_pETColorOverrideEnable->GetIVal()) { clr.r = max(0.f, min(1.f, m_pETColorOverrideR->GetFVal())); clr.g = max(0.f, min(1.f, m_pETColorOverrideG->GetFVal())); clr.b = max(0.f, min(1.f, m_pETColorOverrideB->GetFVal())); } clr.a *= iterList->params.fadeTime / iterList->totalFadeTime; // Apply fade out time to alpha float clrAry[4] = {clr.r, clr.g, clr.b, clr.a}; gEnv->pRenderer->Draw2dLabel( screenPos.x, screenPos.y, fontSize, clrAry, true, "%s", iterList->params.text.c_str() ); } } }
void CPersistantDebug::PostUpdateTags(float frameTime, SObj& obj) { Vec3 baseCenterPos; float heightAboveBase(0.f); if (!GetEntityParams(obj.entityId, baseCenterPos, heightAboveBase)) return; // Check if entity is outside of global distance maximum or behind camera CCamera &cam = GetISystem()->GetViewCamera(); float distFromCam = (cam.GetPosition() - baseCenterPos).GetLength(); float maxDist = m_pETMaxDisplayDistance->GetFVal(); bool isOutOfRange(maxDist >= 0.f && distFromCam > maxDist); bool isBehindCamera(cam.GetViewdir().Dot(baseCenterPos - cam.GetPosition()) <= 0); heightAboveBase = max(obj.entityHeight, heightAboveBase); // never let stored entity height get smaller obj.entityHeight = heightAboveBase; // update stored position heightAboveBase += 0.2f; // make tags start a little above the entity std::vector<TListTag::iterator> toClear; for (TListTag::iterator iterList = obj.tags.begin(); iterList != obj.tags.end(); ++iterList) { iterList->vScreenPos.zero(); if (iterList->params.visibleTime > 0.0f) { iterList->params.visibleTime -= frameTime; if (iterList->params.visibleTime < 0.0f) { // If visibleTime has hit 0, make sure any spillover gets applied to fade time iterList->params.fadeTime += iterList->params.visibleTime; } } else { iterList->params.fadeTime -= frameTime; } if (iterList->params.fadeTime < 0.0f) { toClear.push_back(iterList); } else { if (isOutOfRange || isBehindCamera || 1==m_pETHideAll->GetIVal() || (1==m_pETHideBehaviour->GetIVal() && iterList->params.tagContext.compareNoCase("behaviour") == 0) || (1==m_pETHideReadability->GetIVal() && iterList->params.tagContext.compareNoCase("readability") == 0) || (1==m_pETHideAIDebug->GetIVal() && iterList->params.tagContext.compareNoCase("aidebug") == 0) || (1==m_pETHideFlowgraph->GetIVal() && iterList->params.tagContext.compareNoCase("flowgraph") == 0) || (1==m_pETHideScriptBind->GetIVal() && iterList->params.tagContext.compareNoCase("scriptbind") == 0)) continue; // Check if entity is outside of max distance for this tag float tagMaxDist = iterList->params.viewDistance; if (tagMaxDist >= 0.f && distFromCam > tagMaxDist) continue; float distanceFix = distFromCam * 0.015f; // this constant found through trial and error float riseAmount(0.0f); if (iterList->params.staticId == "") riseAmount = 2.0f * distanceFix * (1 - (obj.timeRemaining / obj.totalTime)); Vec3 tagPos(baseCenterPos.x, baseCenterPos.y, baseCenterPos.z + heightAboveBase + riseAmount); Vec3 screenPos(ZERO); gEnv->pRenderer->ProjectToScreen(tagPos.x, tagPos.y, tagPos.z, &screenPos.x, &screenPos.y, &screenPos.z); iterList->vScreenPos = screenPos; } } while (!toClear.empty()) { obj.tags.erase(toClear.back()); toClear.pop_back(); } }
void AddFlare(const Vec2f & pos, float sm, short typ, Entity * io, bool bookDraw) { size_t oldest = 0; size_t i; for(i = 0; i < g_magicFlaresMax; i++) { if(!g_magicFlares[i].exist) { break; } if(g_magicFlares[i].tolive < g_magicFlares[oldest].tolive) { oldest = i; } } if(i >= g_magicFlaresMax) { removeFlare(g_magicFlares[oldest]); i = oldest; } MagicFlare & flare = g_magicFlares[i]; flare.exist = 1; g_magicFlaresCount++; flare.bDrawBitmap = bookDraw; flare.io = io; if(io) { flare.flags = 1; io->flarecount++; } else { flare.flags = 0; } flare.pos.x = pos.x - Random::getf(0.f, 4.f); flare.pos.y = pos.y - Random::getf(0.f, 4.f); if(!bookDraw) { if(io) { float vx = -(flare.pos.x - g_size.center().x) * 0.2173913f; float vy = (flare.pos.y - g_size.center().y) * 0.1515151515151515f; flare.p = io->pos; flare.p += angleToVectorXZ(io->angle.getYaw() + vx) * 100.f; flare.p.y += std::sin(glm::radians(MAKEANGLE(io->angle.getPitch() + vy))) * 100.f - 150.f; } else { Vec3f screenPos(1.0f * (pos.x - float(g_size.width() / 2)) * 156.f / (640.f * g_sizeRatio.y), 0.75f * (pos.y - float(g_size.height() / 2)) * 156.f / (480.f * g_sizeRatio.y), 75.f); flare.p = Vec3f(glm::inverse(g_preparedCamera.m_worldToView) * Vec4f(screenPos, 1.0f)); } } else { flare.p = Vec3f(flare.pos.x, flare.pos.y, 0.001f); } switch(g_magicFlareCurrentColor) { case 0: { flare.rgb = Color3f(0.4f, 0.f, 0.4f) + Color3f(2.f / 3, 2.f / 3, 2.f / 3) * randomColor3f(); break; } case 1: { flare.rgb = Color3f(0.5f, 0.5f, 0.f) + Color3f(0.625f, 0.625f, 0.55f) * randomColor3f(); break; } case 2: { flare.rgb = Color3f(0.4f, 0.f, 0.f) + Color3f(2.f / 3, 0.55f, 0.55f) * randomColor3f(); break; } default: arx_unreachable(); } static const float FLARE_MUL = 2.f; if(typ == -1) { float zz = eeMousePressed1() ? 0.29f : ((sm > 0.5f) ? Random::getf() : 1.f); if(zz < 0.2f) { flare.type = 2; flare.size = Random::getf(42.f, 84.f); flare.tolive = PlatformDurationMsf(Random::getf(800.f, 1600.f) * FLARE_MUL); } else if(zz < 0.5f) { flare.type = 3; flare.size = Random::getf(16.f, 68.f); flare.tolive = PlatformDurationMsf(Random::getf(800.f, 1600.f) * FLARE_MUL); } else { flare.type = 1; flare.size = Random::getf(32.f, 56.f) * sm; flare.tolive = PlatformDurationMsf(Random::getf(1700.f, 2200.f) * FLARE_MUL); } } else { flare.type = (Random::getf() > 0.8f) ? 1 : 4; flare.size = Random::getf(64.f, 102.f) * sm; flare.tolive = PlatformDurationMsf(Random::getf(1700.f, 2200.f) * FLARE_MUL); } flare.dynlight = LightHandle(); for(unsigned int kk = 0; kk < 3; kk++) { if(Random::getf() < 0.5f) { continue; } PARTICLE_DEF * pd = createParticle(); if(!pd) { break; } if(!bookDraw) { pd->m_flags = FADE_IN_AND_OUT | ROTATING | DISSIPATING; if(!io) { pd->m_flags |= PARTICLE_NOZBUFFER; } } else { pd->m_flags = FADE_IN_AND_OUT; } pd->ov = flare.p + arx::randomVec(-5.f, 5.f); pd->move = Vec3f(0.f, 5.f, 0.f); pd->scale = Vec3f(-2.f); pd->tolive = 1300 + kk * 100 + Random::getu(0, 800); pd->tc = fire2; if(kk == 1) { pd->move.y = 4.f; pd->siz = 1.5f; } else { pd->siz = Random::getf(1.f, 2.f); } pd->rgb = flare.rgb * (2.f / 3); pd->m_rotation = 1.2f; if(bookDraw) { pd->is2D = true; } } }