jiangqiu Posted July 5, 2016 Share Posted July 5, 2016 Hi everyone, There have a question about mouse chose precision, I have input a object(.mesh ) in the scene, and I try to chose it by mouse click, but now I have a question that the mouse click around the model but not on the model I can chose the model too. my model input by C++ as follow: my model input code: ObjectMeshStaticPtr mesh; mesh = ObjectMeshStatic::create(modelPath.c_str()); mesh->setMaterial(texture_material_0, "*"); The code about mouse chose (It's refer to the Unigine demo "Orbits"): int checkIntersection() { if (Unigine::Editor::get()->isLoaded()) return 1; if (Unigine::ControlsApp::get()->isMouseEnabled()) return 1; if (Unigine::App::get()->getMouseButtonState(Unigine::App::BUTTON_LEFT) ) { mat4 projection; float x0 = float(Unigine::App::get()->getMouseX() - 1) / Unigine::App::get()->getWidth(); float y0 = float(Unigine::App::get()->getMouseY() - 1) / Unigine::App::get()->getHeight(); float x1 = float(Unigine::App::get()->getMouseX() + 1) / Unigine::App::get()->getWidth(); float y1 = float(Unigine::App::get()->getMouseY() + 1) / Unigine::App::get()->getHeight(); getPlayerMouseSelection2(x0, y0, x1, y1, projection); PlayerPtr player = Game::get()->getPlayer(); if (Unigine::Editor::get()->getPlayer().get() != NULL) { player = Unigine::Editor::get()->getPlayer(); } //bondbox Mat4 modelview = player->getIWorldTransform(); WorldBoundFrustum bound_frustum = WorldBoundFrustum(projection, modelview); Vector< NodePtr > nodes; Unigine::World::get()->getIntersection(bound_frustum, -1, nodes); for (int i = 0; i < Models.size(); i++) { Models[i]->isSelected = false; } if (nodes.size() != 0) { ObjectMeshStaticPtr OneOfSelected; NodePtr n; for (int i = 0; i < nodes.size(); i++) { n = nodes[i]; const char *name = "ObjectMeshStatic"; if (strcmp(n.get()->getTypeName(), name) == 0) { for (int i = 0; i < Models.size(); i++) { if (n.get()->getName() == Models[i]->mesh.get()->getName()) { Models[i]->isSelected = true; } } } } } } return 0; } // calculate the projection matrix int getPlayerMouseSelection2(float x0, float y0, float x1, float y1, mat4 &projection) { PlayerPtr player = Game::get()->getPlayer(); if (Unigine::Editor::get()->getPlayer().get() != NULL) { player = Unigine::Editor::get()->getPlayer(); } int width = Unigine::App::get()->getWidth(); int height = Unigine::App::get()->getHeight(); projection = player->getProjection(); projection.m00 *= float(height) / width; vec3 points[8]; points[0] = vec3(-1.0f, -1.0f, -1.0f); points[1] = vec3(1.0f, -1.0f, -1.0f); points[2] = vec3(-1.0f, 1.0f, -1.0f); points[3] = vec3(1.0f, 1.0f, -1.0f); points[4] = vec3(-1.0f, -1.0f, 1.0f); points[5] = vec3(1.0f, -1.0f, 1.0f); points[6] = vec3(-1.0f, 1.0f, 1.0f); points[7] = vec3(1.0f, 1.0f, 1.0f); mat4 iprojection = inverse(projection); for (int i = 0; i < 8; i++) { vec4 p = iprojection * vec4(points[i]); points[i] = vec3(p) / p.w; } float dx = points[1].x - points[0].x; float dy = points[0].y - points[2].y; x0 = points[0].x + dx * x0; x1 = points[0].x + dx * x1; y0 = points[2].y + dy * y0; y1 = points[2].y + dy * y1; if (projection.m32 == 0.0f) projection = ortho(x0, x1, y0, y1, -points[0].z, -points[4].z); else projection = frustum(x0, x1, y0, y1, -points[0].z, -points[4].z); return 1; } By those codes I can chose my model but not precision, when the mouse click almost everywhere in the red circle I can chose the model but not when the mouse click on the model only I can chose the model: Do you konw how can I make the mouse chose range more precise? Thanks! Link to comment
honya Posted July 5, 2016 Share Posted July 5, 2016 Hi, why don't use point to point intersection? Link to comment
ded Posted July 6, 2016 Share Posted July 6, 2016 Hi, Please try using the following method: Ptr<Object> World::getIntersection(const Math::Vec3 &p0, const Math::Vec3 &p1, int mask, const Ptr<WorldIntersection> &v); Here's the usage example: bool getPlayerMouseDirection(const PlayerPtr &player, float mouse_x, float mouse_y, float width, float height, Vec3 *p0, Vec3 *p1) { if (player.get() == NULL) return false; mat4 projection = player->getProjection(); Mat4 imodelview = player->getWorldTransform(); projection.m00 *= height / width; float x = -(mouse_x / width * 2.0f - 1.0f + projection.m02) / projection.m00; float y = (mouse_y / height * 2.0f - 1.0f + projection.m12) / projection.m11; if (projection.m32 == 0.0f) { *p0 = imodelview * Vec3(-x, -y, -1.0f); *p1 = imodelview * Vec3(-x, -y, 1.0f); } else { *p0 = Vec3(imodelview.m03, imodelview.m13, imodelview.m23); *p1 = imodelview * Vec3(x, y, 1.0f); } *p1 = *p0 - normalize(*p1 - *p0) * player->getZFar(); return true; } ObjectPtr getIntersection() { PlayerPtr player = Game::get()->getPlayer(); float x = App::get()->getMouseX(); float y = App::get()->getMouseY(); float width = App::get()->getWidth(); float height = App::get()->getHeight(); Vec3 p0, p1; if (!getPlayerMouseDirection(player, x, y, width, height, &p0, &p1)) return ObjectPtr(); WorldIntersectionPtr intersection = WorldIntersection::create(); ObjectPtr object = Unigine::World::get()->getIntersection(p0, p1, ~0, intersection); // object.get() == NULL when no object is intersected by a ray return object; } You can found more elaborate implementation of getPlayerMouseDirection() on UnigineScript in the SDK/data/core/scripts/utils.h file. Link to comment
Recommended Posts