How to direct a character parallel to the ground?

I try

if (RaycastDown(hitPos, hitDrawable, normal))
{
    node.rotation = Quaternion(normal.x, node.rotation.yaw, normal.z);
}

but it does not work. Please help me :slight_smile:

Source: github.com/1vanK/Habr/blob/mast … oScript.as

Do I understand correctly that normal is not calculated really ?

void Drawable::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    float distance = query.ray_.HitDistance(GetWorldBoundingBox());
    if (distance < query.maxDistance_)
    {
        RayQueryResult result;
        result.position_ = query.ray_.origin_ + distance * query.ray_.direction_;
        result.normal_ = -query.ray_.direction_;  // <------------------------------------------------------------
        result.distance_ = distance;
        result.drawable_ = this;
        result.node_ = GetNode();
        result.subObject_ = M_MAX_UNSIGNED;
        results.Push(result);
    }
}

That is in the base class, which doesn’t actually understand the geometry. E.g. StaticModel raycast should return the normal correctly.

If I’m not mistaken, there’s already a snippet from Vehicle or Water Demo which demonstrates actual placement (or something similar) of objects (mushrooms) parallel from Terrain. Maybe you could derive something from that example…

Oh, thanks. It works

if (RaycastDown(hitPos, hitDrawable, normal))
{
    Quaternion grndTilt = Quaternion(Vector3(0.0f, 1.0f, 0.0f), normal);
    node.rotation = grndTilt * Quaternion(0.0f, node.rotation.yaw, 0.0f);
}

Another method from answers.unity3d.com/questions/16 … ormal.html
It gives smoother results.

        Vector3 corner1 = node.position + Vector3(-1.0f, 0.0f, -1.0f);
        Vector3 corner2 = node.position + Vector3(1.0f, 0.0f, -1.0f);
        Vector3 corner3 = node.position + Vector3(1.0f, 0.0f, 1.0f);
        Vector3 corner4 = node.position + Vector3(-1.0f, 0.0f, 1.0f);
        
        Vector3 hit1, hit2, hit3, hit4;
        
        bool b1 = RaycastDown(corner1, hit1, hitDrawable);
        bool b2 = RaycastDown(corner2, hit2, hitDrawable);
        bool b3 = RaycastDown(corner3, hit3, hitDrawable);
        bool b4 = RaycastDown(corner4, hit4, hitDrawable);
        
        if (!b1) log.Warning("b1");
        if (!b2) log.Warning("b2");
        if (!b3) log.Warning("b3");
        if (!b4) log.Warning("b4"); // fix it case

       
        Vector3 normal = hit1.CrossProduct(hit2) + hit2.CrossProduct(hit3) +
                         hit3.CrossProduct(hit4) + hit4.CrossProduct(hit1);
        normal.Normalize();
        normal = -normal;

        Quaternion grndTilt = Quaternion(Vector3(0.0f, 1.0f, 0.0f), normal);
        node.rotation = grndTilt * Quaternion(0.0f, node.rotation.yaw, 0.0f);

...

    bool RaycastDown(Vector3 from, Vector3& hitPos, Drawable@& hitDrawable)
    {
        hitDrawable = null;
        Ray ray(from + Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, -1.0f, 0.0f));
        RayQueryResult result = scene.octree.RaycastSingle(ray, RAY_TRIANGLE, 1000, DRAWABLE_GEOMETRY, 1);

        if (result.drawable is null)
            return false;

        hitPos = result.position;
        hitDrawable = result.drawable;
        return true;
    }