Exemplo n.º 1
0
void SphericalDeformation::setScreenUniforms(ptr<SceneNode> context, ptr<TerrainQuad> q, ptr<Program> prog) const
{
    vec3d p0 = vec3d(q->ox, q->oy, R);
    vec3d p1 = vec3d(q->ox + q->l, q->oy, R);
    vec3d p2 = vec3d(q->ox, q->oy + q->l, R);
    vec3d p3 = vec3d(q->ox + q->l, q->oy + q->l, R);
    vec3d pc = (p0 + p3) * 0.5;
    double l0, l1, l2, l3;
    vec3d v0 = p0.normalize(&l0);
    vec3d v1 = p1.normalize(&l1);
    vec3d v2 = p2.normalize(&l2);
    vec3d v3 = p3.normalize(&l3);

    if (screenQuadCornersU != NULL) {
        mat4d deformedCorners = mat4d(
            v0.x * R, v1.x * R, v2.x * R, v3.x * R,
            v0.y * R, v1.y * R, v2.y * R, v3.y * R,
            v0.z * R, v1.z * R, v2.z * R, v3.z * R,
            1.0, 1.0, 1.0, 1.0);
        screenQuadCornersU->setMatrix((localToScreen * deformedCorners).cast<float>());
    }

    if (screenQuadVerticalsU != NULL) {
        mat4d deformedVerticals = mat4d(
            v0.x, v1.x, v2.x, v3.x,
            v0.y, v1.y, v2.y, v3.y,
            v0.z, v1.z, v2.z, v3.z,
            0.0, 0.0, 0.0, 0.0);
        screenQuadVerticalsU->setMatrix((localToScreen * deformedVerticals).cast<float>());
    }

    if (screenQuadCornerNormsU != NULL) {
        screenQuadCornerNormsU->set(vec4d(l0, l1, l2, l3).cast<float>());
    }
    if (tangentFrameToWorldU != NULL) {
        vec3d uz = pc.normalize();
        vec3d ux = vec3d::UNIT_Y.crossProduct(uz).normalize();
        vec3d uy = uz.crossProduct(ux);

        mat4d ltow = context->getLocalToWorld();
        mat3d tangentFrameToWorld = mat3d(
            ltow[0][0], ltow[0][1], ltow[0][2],
            ltow[1][0], ltow[1][1], ltow[1][2],
            ltow[2][0], ltow[2][1], ltow[2][2]) *
        mat3d(
            ux.x, uy.x, uz.x,
            ux.y, uy.y, uz.y,
            ux.z, uy.z, uz.z);
        tangentFrameToWorldU->setMatrix(tangentFrameToWorld.cast<float>());
    }
}
Exemplo n.º 2
0
mat4d CylindricalDeformation::localToDeformedDifferential(const vec3d &localPt, bool clamp) const
{
    float alpha = (float) localPt.y / R;
    return mat4d(1.0, 0.0, 0.0, localPt.x,
        0.0, cos(alpha), -sin(alpha), R * sin(alpha),
        0.0, sin(alpha), cos(alpha), - R * cos(alpha),
        0.0, 0.0, 0.0, 1.0);
}
Exemplo n.º 3
0
mat4d SphericalDeformation::deformedToTangentFrame(const vec3d &deformedPt) const
{
    vec3d Uz = deformedPt.normalize();
    vec3d Ux = (vec3d::UNIT_Y.crossProduct(Uz)).normalize();
    vec3d Uy = Uz.crossProduct(Ux);
    return mat4d(Ux.x, Ux.y, Ux.z, 0.0,
        Uy.x, Uy.y, Uy.z, 0.0,
        Uz.x, Uz.y, Uz.z, -R,
        0.0, 0.0, 0.0, 1.0);
}
Exemplo n.º 4
0
void IkSolver::updateBoneTransforms(const Bone *parent, const Bone &b, const mat4d &base) const
{
	const BoneState &bs = boneStates[b.id];

	if (parent == 0)
		bs.boneToWorld = base * mat4d(bs.rot);
	else
	{
		const Bone::Connection &c = *b.findJointWith(*parent);
		bs.boneToWorld = base * mat4d(bs.rot) * vmath::translation_matrix(-c.pos);
	}

	for (int i = 0; i < (int)b.joints.size(); ++i)
	{
		const Bone::Connection &c = b.joints[i];
		Bone &bn = *c.to;
		if (&bn != parent)
			updateBoneTransforms(&b, bn, bs.boneToWorld * vmath::translation_matrix(c.pos));
	}
}
Exemplo n.º 5
0
mat4d CylindricalDeformation::deformedToTangentFrame(const vec3d &deformedPt) const
{
    vec3d Uz = vec3d(0.0, -deformedPt.y, -deformedPt.z).normalize();
    vec3d Ux = vec3d::UNIT_X;
    vec3d Uy = Uz.crossProduct(Ux);
    vec3d O = vec3d(deformedPt.x, -Uz.y * R, -Uz.z * R);
    return mat4d(Ux.x, Ux.y, Ux.z, -O.dotproduct(Ux),
        Uy.x, Uy.y, Uy.z, -O.dotproduct(Uy),
        Uz.x, Uz.y, Uz.z, -O.dotproduct(Uz),
        0.0, 0.0, 0.0, 1.0);
}
Exemplo n.º 6
0
void IkSolver::resetPose()
{
	rootPos = rootBone->worldPos;

	for (int i = 0; i < (int)skeleton.numBones(); ++i)
	{
		const Bone &b = skeleton[i];
		boneStates[i].boneToWorld = vmath::translation_matrix(b.worldPos) * mat4d(b.defaultOrient);
	}

	resetBoneRot(0, *rootBone);

	//updateBoneTransforms();
}
Exemplo n.º 7
0
mat4d SphericalDeformation::localToDeformedDifferential(const vec3d &localPt, bool clamp) const
{
    if (!isFinite(localPt.x) || !isFinite(localPt.y) || !isFinite(localPt.z)) {
        return mat4d::IDENTITY;
    }

    vec3d pt = localPt;
    if (clamp) {
        pt.x = pt.x - floor((pt.x + R) / (2.0 * R)) * 2.0 * R;
        pt.y = pt.y - floor((pt.y + R) / (2.0 * R)) * 2.0 * R;
    }

    double l = pt.x*pt.x + pt.y*pt.y + R*R;
    double c0 = 1.0 / sqrt(l);
    double c1 = c0 * R / l;
    return mat4d((pt.y*pt.y + R*R)*c1, -pt.x*pt.y*c1, pt.x*c0, R*pt.x*c0,
        -pt.x*pt.y*c1, (pt.x*pt.x + R*R)*c1, pt.y*c0, R*pt.y*c0,
        -pt.x*R*c1, -pt.y*R*c1, R*c0, (R*R)*c0,
        0.0, 0.0, 0.0, 1.0);
}
Exemplo n.º 8
0
bool DrawOceanTask::Impl::run()
{
    if (Logger::DEBUG_LOGGER != NULL) {
        Logger::DEBUG_LOGGER->log("OCEAN", "DrawOcean");
    }
    ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer();
    ptr<Program> prog = SceneManager::getCurrentProgram();

    if (o->nbWavesU == NULL) {
        o->nbWavesU = prog->getUniform1f("nbWaves");
        o->wavesU = prog->getUniformSampler("wavesSampler");
        o->cameraToOceanU = prog->getUniformMatrix4f("cameraToOcean");
        o->screenToCameraU = prog->getUniformMatrix4f("screenToCamera");
        o->cameraToScreenU = prog->getUniformMatrix4f("cameraToScreen");
        o->oceanToCameraU = prog->getUniformMatrix3f("oceanToCamera");
        o->oceanToWorldU = prog->getUniformMatrix4f("oceanToWorld");
        o->oceanCameraPosU = prog->getUniform3f("oceanCameraPos");
        o->oceanSunDirU = prog->getUniform3f("oceanSunDir");
        o->horizon1U = prog->getUniform3f("horizon1");
        o->horizon2U = prog->getUniform3f("horizon2");
        o->timeU = prog->getUniform1f("time");
        o->radiusU = prog->getUniform1f("radius");
        o->heightOffsetU = prog->getUniform1f("heightOffset");
        o->lodsU = prog->getUniform4f("lods");

        assert(o->nbWavesU != NULL);
        o->generateWaves();
    }

    vector< ptr<TileSampler> > uniforms;
    SceneNode::FieldIterator ui = n->getFields();
    while (ui.hasNext()) {
        ptr<TileSampler> u = ui.next().cast<TileSampler>();
        if (u != NULL && u->getTerrain(0) != NULL) {
            u->setTileMap();
        }
    }

    // compute ltoo = localToOcean transform, where ocean frame = tangent space at
    // camera projection on sphere o->radius in local space
    mat4d ctol = n->getLocalToCamera().inverse();
    vec3d cl = ctol * vec3d::ZERO; // camera in local space

    if ((o->radius == 0.0 && cl.z > o->zmin) ||
        (o->radius > 0.0 && cl.length() > o->radius + o->zmin) ||
        (o->radius < 0.0 && vec2d(cl.y, cl.z).length() < -o->radius - o->zmin))
    {
        o->oldLtoo = mat4d::IDENTITY;
        o->offset = vec3d::ZERO;
        return true;
    }

    vec3d ux, uy, uz, oo;

    if (o->radius == 0.0) {
        // flat ocean
        ux = vec3d::UNIT_X;
        uy = vec3d::UNIT_Y;
        uz = vec3d::UNIT_Z;
        oo = vec3d(cl.x, cl.y, 0.0);
    } else if (o->radius > 0.0) {
        // spherical ocean
        uz = cl.normalize(); // unit z vector of ocean frame, in local space
        if (o->oldLtoo != mat4d::IDENTITY) {
            ux = vec3d(o->oldLtoo[1][0], o->oldLtoo[1][1], o->oldLtoo[1][2]).crossProduct(uz).normalize();
        } else {
            ux = vec3d::UNIT_Z.crossProduct(uz).normalize();
        }
        uy = uz.crossProduct(ux); // unit y vector
        oo = uz * o->radius; // origin of ocean frame, in local space
    } else {
        // cylindrical ocean
        uz = vec3d(0.0, -cl.y, -cl.z).normalize();
        ux = vec3d::UNIT_X;
        uy = uz.crossProduct(ux);
        oo = vec3d(cl.x, 0.0, 0.0) + uz * o->radius;
    }

    mat4d ltoo = mat4d(
        ux.x, ux.y, ux.z, -ux.dotproduct(oo),
        uy.x, uy.y, uy.z, -uy.dotproduct(oo),
        uz.x, uz.y, uz.z, -uz.dotproduct(oo),
        0.0,  0.0,  0.0,  1.0);
    // compute ctoo = cameraToOcean transform
    mat4d ctoo = ltoo * ctol;

    if (o->oldLtoo != mat4d::IDENTITY) {
        vec3d delta = ltoo * (o->oldLtoo.inverse() * vec3d::ZERO);
        o->offset += delta;
    }
    o->oldLtoo = ltoo;

    mat4d ctos = n->getOwner()->getCameraToScreen();
    mat4d stoc = ctos.inverse();
    vec3d oc = ctoo * vec3d::ZERO;

    if (o->oceanSunDirU != NULL) {
        // TODO how to get sun dir in a better way?
        SceneManager::NodeIterator i = n->getOwner()->getNodes("light");
        if (i.hasNext()) {
            ptr<SceneNode> l = i.next();
            vec3d worldSunDir = l->getLocalToParent() * vec3d::ZERO;
            vec3d oceanSunDir = ltoo.mat3x3() * (n->getWorldToLocal().mat3x3() * worldSunDir);
            o->oceanSunDirU->set(oceanSunDir.cast<float>());
        }
    }

    vec4<GLint> screen = fb->getViewport();

    vec4d frustum[6];
    SceneManager::getFrustumPlanes(ctos, frustum);
    vec3d left = frustum[0].xyz().normalize();
    vec3d right = frustum[1].xyz().normalize();
    float fov = (float) safe_acos(-left.dotproduct(right));
    float pixelSize = atan(tan(fov / 2.0f) / (screen.w / 2.0f)); // angle under which a screen pixel is viewed from the camera

    o->cameraToOceanU->setMatrix(ctoo.cast<float>());
    o->screenToCameraU->setMatrix(stoc.cast<float>());
    o->cameraToScreenU->setMatrix(ctos.cast<float>());
    o->oceanToCameraU->setMatrix(ctoo.inverse().mat3x3().cast<float>());
    o->oceanCameraPosU->set(vec3f(float(-o->offset.x), float(-o->offset.y), float(oc.z)));
    if (o->oceanToWorldU != NULL) {
        o->oceanToWorldU->setMatrix((n->getLocalToWorld() * ltoo.inverse()).cast<float>());
    }

    if (o->horizon1U != NULL) {
        float h = oc.z;
        vec3d A0 = (ctoo * vec4d((stoc * vec4d(0.0, 0.0, 0.0, 1.0)).xyz(), 0.0)).xyz();
        vec3d dA = (ctoo * vec4d((stoc * vec4d(1.0, 0.0, 0.0, 0.0)).xyz(), 0.0)).xyz();
        vec3d B = (ctoo * vec4d((stoc * vec4d(0.0, 1.0, 0.0, 0.0)).xyz(), 0.0)).xyz();
        if (o->radius == 0.0) {
            o->horizon1U->set(vec3f(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0));
            o->horizon2U->set(vec3f::ZERO);
        } else {
            double h1 = h * (h + 2.0 * o->radius);
            double h2 = (h + o->radius) * (h + o->radius);
            double alpha = B.dotproduct(B) * h1 - B.z * B.z * h2;
            double beta0 = (A0.dotproduct(B) * h1 - B.z * A0.z * h2) / alpha;
            double beta1 = (dA.dotproduct(B) * h1 - B.z * dA.z * h2) / alpha;
            double gamma0 = (A0.dotproduct(A0) * h1 - A0.z * A0.z * h2) / alpha;
            double gamma1 = (A0.dotproduct(dA) * h1 - A0.z * dA.z * h2) / alpha;
            double gamma2 = (dA.dotproduct(dA) * h1 - dA.z * dA.z * h2) / alpha;
            o->horizon1U->set(vec3f(-beta0, -beta1, 0.0));
            o->horizon2U->set(vec3f(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2));
        }
    }

    o->timeU->set(n->getOwner()->getTime() * 1e-6);
    if (o->radiusU != NULL) {
        o->radiusU->set(o->radius < 0.0 ? -o->radius : o->radius);
    }
    o->heightOffsetU->set(-o->meanHeight);
    o->lodsU->set(vec4f(o->resolution,
            pixelSize * o->resolution,
            log(o->lambdaMin) / log(2.0f),
            (o->nbWavesU->get() - 1.0f) / (log(o->lambdaMax) / log(2.0f) -  log(o->lambdaMin) / log(2.0f))));

    if (o->screenGrid == NULL || o->screenWidth != screen.z || o->screenHeight != screen.w) {
        o->screenWidth = screen.z;
        o->screenHeight = screen.w;
        o->screenGrid = new Mesh<vec2f, unsigned int>(TRIANGLES, GPU_STATIC);
        o->screenGrid->addAttributeType(0, 2, A32F, false);

        float f = 1.25f;
        int NX = int(f * screen.z / o->resolution);
        int NY = int(f * screen.w / o->resolution);
        for (int i = 0; i < NY; ++i) {
            for (int j = 0; j < NX; ++j) {
                o->screenGrid->addVertex(vec2f(2.0*f*j/(NX-1.0f)-f, 2.0*f*i/(NY-1.0f)-f));
            }
        }
        for (int i = 0; i < NY-1; ++i) {
            for (int j = 0; j < NX-1; ++j) {
                o->screenGrid->addIndice(i*NX+j);
                o->screenGrid->addIndice(i*NX+j+1);
                o->screenGrid->addIndice((i+1)*NX+j);
                o->screenGrid->addIndice((i+1)*NX+j);
                o->screenGrid->addIndice(i*NX+j+1);
                o->screenGrid->addIndice((i+1)*NX+j+1);
            }
        }
    }

    fb->draw(prog, *(o->screenGrid));

    return true;
}