Jump to content

How to make a node snap to the terrain surface using C++ ?


photo

Recommended Posts

Hi,

I want to make a node snap to the terrain surface while moving it at runtime. It is like the result of "Snap to Surface" button in the editor. But I don't how to do it with C++ APIs.

Link to comment

Hi songtao.han,

World::getIntersection() is what you need in this case

Suppose you have a GlobalTerrain object on your scene and some node that you'd like to snap to the terrain's surface. You can use the following function for snapping(call it each frame in the update()):

void doIntersection(ObjectTerrainGlobalPtr terrain, NodePtr node) {
	//Get mouse direction
	Vec3 p0, p1;

	int width = App::get()->getWidth();
	int height = App::get()->getHeight();
	// get the current X and Y coordinates of the mouse pointer
	int mouse_x = App::get()->getMouseX();
	int mouse_y = App::get()->getMouseY();
	// get the mouse direction from the player's position (p0) to the mouse cursor pointer (p1)
	Game::get()->getPlayer()->getDirectionFromScreen(p0, p1, mouse_x, mouse_y, width, height);

	//Only 10km intersection
	p1 = p0 + normalize(p1 - p0) * 10000;
	int is_intersection;

	WorldIntersectionPtr intersection = WorldIntersection::create();
	ObjectPtr object = World::get()->getIntersection(p0, p1, 1, intersection);

	//Check if there was intersection with the landscape and change node position
	if (object == terrain->getObject()) {
		Vec3 point = intersection->getPoint();
		point.z += node->getWorldBoundSphere().getRadius();
		node->setWorldPosition(point);
	}
}

For more information on intersections please refer to this article.

Thank you!

Link to comment
On 10/31/2018 at 5:03 PM, fox said:

Hi songtao.han,

World::getIntersection() is what you need in this case

Suppose you have a GlobalTerrain object on your scene and some node that you'd like to snap to the terrain's surface. You can use the following function for snapping(call it each frame in the update()):


void doIntersection(ObjectTerrainGlobalPtr terrain, NodePtr node) {
	//Get mouse direction
	Vec3 p0, p1;

	int width = App::get()->getWidth();
	int height = App::get()->getHeight();
	// get the current X and Y coordinates of the mouse pointer
	int mouse_x = App::get()->getMouseX();
	int mouse_y = App::get()->getMouseY();
	// get the mouse direction from the player's position (p0) to the mouse cursor pointer (p1)
	Game::get()->getPlayer()->getDirectionFromScreen(p0, p1, mouse_x, mouse_y, width, height);

	//Only 10km intersection
	p1 = p0 + normalize(p1 - p0) * 10000;
	int is_intersection;

	WorldIntersectionPtr intersection = WorldIntersection::create();
	ObjectPtr object = World::get()->getIntersection(p0, p1, 1, intersection);

	//Check if there was intersection with the landscape and change node position
	if (object == terrain->getObject()) {
		Vec3 point = intersection->getPoint();
		point.z += node->getWorldBoundSphere().getRadius();
		node->setWorldPosition(point);
	}
}

For more information on intersections please refer to this article.

Thank you!

Sorry for the delay! But this isn't what I want. I need not only to place a node on the terrain surface but also to change it's orientation automatically by the terrain's hypsography. Shown in the picture below:

1509103013_QQ20181105152753.png.71b3b1229f33ea0f33fec6fb86944285.png

Link to comment

Hi Songtao,

I see, in this case you'll need information about the normal at the intersection point to change your node's orientation. You can use the World::getIntersection() method

that uses an instance of the WorldIntersectionNormal class to store intersection info.

// create an instance of the WorldIntersectionNormal class to get the result
WorldIntersectionNormalPtr intersection = WorldIntersectionNormal::create();

// create an instance for intersected object and check the intersection
ObjectPtr object = World::get()->getIntersection(p0,p1,1,intersection);

// if the intersection has been occurred, change the parameter of the object's material
if(object)
{
      // show intersection details in console
      Log::message("Normal: type %s coordinates (%f %f %f)\n", typeid(intersection->getNormal()).name(),
            intersection->getNormal().x,
            intersection->getNormal().y,
            intersection->getNormal().z);
      Log::message("Point: (%f %f %f) index: %i \n", 
            intersection->getPoint().x, 
            intersection->getPoint().y, 
            intersection->getPoint().z, 
            intersection->getIndex());
  }
}

Then you can use it to get information about the intersection point and normal to orient your node properly.

Thank you!

Link to comment
3 hours ago, fox said:

Hi Songtao,

I see, in this case you'll need information about the normal at the intersection point to change your node's orientation. You can use the World::getIntersection() method

that uses an instance of the WorldIntersectionNormal class to store intersection info.


// create an instance of the WorldIntersectionNormal class to get the result
WorldIntersectionNormalPtr intersection = WorldIntersectionNormal::create();

// create an instance for intersected object and check the intersection
ObjectPtr object = World::get()->getIntersection(p0,p1,1,intersection);

// if the intersection has been occurred, change the parameter of the object's material
if(object)
{
      // show intersection details in console
      Log::message("Normal: type %s coordinates (%f %f %f)\n", typeid(intersection->getNormal()).name(),
            intersection->getNormal().x,
            intersection->getNormal().y,
            intersection->getNormal().z);
      Log::message("Point: (%f %f %f) index: %i \n", 
            intersection->getPoint().x, 
            intersection->getPoint().y, 
            intersection->getPoint().z, 
            intersection->getIndex());
  }
}

Then you can use it to get information about the intersection point and normal to orient your node properly.

Thank you!

I know I need to get information about the normal at the intersection point. But I don't know how to change the node's orientation using that. Sorry for the stupid question!

Link to comment
×
×
  • Create New...