Ejemplo n.º 1
0
void
Camera::strafeCamera(float speed)
{
	// Strafing is quite simple if you understand what the cross product is.
	// If you have 2 vectors (say the up vVector and the view vVector) you can
	// use the cross product formula to get a vVector that is 90 degrees from the 2 vectors.
	// For a better explanation on how this works, check out the OpenGL "Normals" tutorial at our site.
	// In our new Update() function, we set the strafing vector (m_vStrafe).  Due
	// to the fact that we need this vector for many things including the strafing
	// movement and camera rotation (up and down), we just calculate it once.
	//
	// Like our MoveCamera() function, we add the strafing vector to our current position
	// and view.  It's as simple as that.  It has already been calculated in Update().

	V3f vStrafe = V3f::cross(mView - mEye, mUp);
	vStrafe.normalize();

	// Add the strafe vector to our position
	*mEye.x += vStrafe.getX() * speed;
	*mEye.z += vStrafe.getZ() * speed;

	// Add the strafe vector to our view
	*mView.x += vStrafe.getX() * speed;
	*mView.z += vStrafe.getZ() * speed;
//	applyToGL();
}
Ejemplo n.º 2
0
void PhongBrdf::randVonMisesFisher3(V3f mu, float kappa, int n, V3f* directions) {


	V3f normal(0,0,1);
	V3f u = mu.cross(normal);
	float cost = dot(mu,normal);
	float sint = u.length();
	u = u.normalize();

	M33f rot(cost + u.x * u.x * (1 - cost),
			u.x * u.y * (1 - cost) - u.z * sint,
			u.x * u.z * (1 - cost) + u.y * sint,
			u.y * u.x * (1 - cost) + u.z * sint,
			cost + u.y * u.y * (1 - cost),
			u.y * u.z * (1 - cost) - u.x * sint,
			u.z * u.x * (1 - cost) - u.y * sint,
			u.z	* u.y * (1 - cost) + u.x * sint,
			cost + u.z * u.z * (1 - cost));

	float c = 2/kappa*(sinh(kappa)); // normalizing constant

	float y, w, v;
	for (int i=0; i < n; i++) {
		y = randomGenerator.RandomFloat();
		w = 1/kappa * log( exp(-kappa) + kappa * c * y );
		v = 2*M_PI*randomGenerator.RandomFloat();

		directions[i].x = sqrt(1-w*w)*cos(v);
		directions[i].y = sqrt(1-w*w)*sin(v);
		directions[i].z = w;

		directions[i] = directions[i]*rot;
	}

}
Ejemplo n.º 3
0
void PhongBrdf::getRandomDirections(const V3f incoming,
			const V3f normal, int n, V3f* directions) {

	V3f R = -incoming - 2 * (dot(-incoming, normal)) * normal;
	R = R.normalize();

	randVonMisesFisher3(R, phongExponent, n, directions);
}
Ejemplo n.º 4
0
void
Camera::mouseRotate(float angleY, float angleZ)
{
	V3f vAxis = V3f::cross(mView - mEye, mUp);
	vAxis.normalize();

	// Rotate around our perpendicular axis and along the y-axis
//	rotateView(angleZ, vAxis);
//	rotateView(angleY, 0.0f, 1.0f, 0.0f);
	rotateView(angleZ, vAxis);
	rotateView(angleY, 0.0f, 1.0f,0.0f);
//	applyToGL();
}
Ejemplo n.º 5
0
/// \todo Use IECore::RadixSort (might still want to use std::sort for small numbers of points - profile to check this)
void PointsPrimitive::depthSort() const
{
	V3f cameraDirection = Camera::viewDirectionInObjectSpace();
	cameraDirection.normalize();

	const vector<V3f> &points = m_memberData->points->readable();
	if( !m_memberData->depthOrder.size() )
	{
		// never sorted before. initialize space.
		m_memberData->depthOrder.resize( points.size() );
		for( unsigned int i=0; i<m_memberData->depthOrder.size(); i++ )
		{
			m_memberData->depthOrder[i] = i;
		}
		m_memberData->depths.resize( points.size() );
	}
	else
	{
		// sorted before. see if the camera direction has changed enough
		// to warrant resorting.
		if( cameraDirection.dot( m_memberData->depthCameraDirection ) > 0.95 )
		{
			return;
		}
	}

	m_memberData->depthCameraDirection = cameraDirection;

	// calculate all distances
	for( unsigned int i=0; i<m_memberData->depths.size(); i++ )
	{
		m_memberData->depths[i] = points[i].dot( m_memberData->depthCameraDirection );
	}

	// sort based on those distances
	SortFn sorter( m_memberData->depths );
	sort( m_memberData->depthOrder.begin(), m_memberData->depthOrder.end(), sorter );
}
Ejemplo n.º 6
0
void CameraController::tumble( const Imath::V2f &p )
{
	V2f d = p - m_data->motionStart;

	V3f centreOfInterestInWorld = V3f( 0, 0, -m_data->centreOfInterest ) * m_data->motionMatrix;
	V3f xAxisInWorld = V3f( 1, 0, 0 );
	m_data->motionMatrix.multDirMatrix( xAxisInWorld, xAxisInWorld );
	xAxisInWorld.normalize();

	M44f t;
	t.translate( centreOfInterestInWorld );

		t.rotate( V3f( 0, -d.x / 100.0f, 0 ) );

		M44f xRotate;
		xRotate.setAxisAngle( xAxisInWorld, -d.y / 100.0f );

		t = xRotate * t;

	t.translate( -centreOfInterestInWorld );

	m_data->transform->matrix = m_data->motionMatrix * t;
}
Ejemplo n.º 7
0
Rgba
EnvmapImage::filteredLookup (V3f d, float r, int n) const
{
    //
    // Filtered environment map lookup: Take n by n point samples
    // from the environment map, clustered around direction d, and
    // combine the samples with a tent filter.
    //
    
    //
    // Depending on the type of map, pick an appropriate function
    // to convert 3D directions to 2D pixel poitions.
    //

    V2f (* dirToPos) (const Box2i &, const V3f &);

    if (_type == ENVMAP_LATLONG)
	dirToPos = dirToPosLatLong;
    else
	dirToPos = dirToPosCube;

    //
    // Pick two vectors, dx and dy, of length r, that are orthogonal
    // to the lookup direction, d, and to each other.
    //

    d.normalize();
    V3f dx, dy;

    if (abs (d.x) > 0.707f)
	dx = (d % V3f (0, 1, 0)).normalized() * r;
    else
	dx = (d % V3f (1, 0, 0)).normalized() * r;

    dy = (d % dx).normalized() * r;

    //
    // Take n by n point samples from the map, and add them up.
    // The directions for the point samples are all within the pyramid
    // defined by the vectors d-dy-dx, d-dy+dx, d+dy-dx, d+dy+dx.
    //

    float wt = 0;

    float cr = 0;
    float cg = 0;
    float cb = 0;
    float ca = 0;

    for (int y = 0; y < n; ++y)
    {
	float ry = float (2 * y + 2) / float (n + 1) - 1;
	float wy = 1 - abs (ry);
	V3f ddy (ry * dy);

	for (int x = 0; x < n; ++x)
	{
	    float rx = float (2 * x + 2) / float (n + 1) - 1;
	    float wx = 1 - abs (rx);
	    V3f ddx (rx * dx);
	    
	    Rgba s = sample (dirToPos (_dataWindow, d + ddx + ddy));

	    float w = wx * wy;
	    wt += w;

	    cr += s.r * w;
	    cg += s.g * w;
	    cb += s.b * w;
	    ca += s.a * w;
	}
    }

    wt = 1 / wt;

    Rgba c;

    c.r = cr * wt;
    c.g = cg * wt;
    c.b = cb * wt;
    c.a = ca * wt;

    return c;
}
Ejemplo n.º 8
0
//-*****************************************************************************
void MeshDrwHelper::draw( const DrawContext & iCtx ) const
{
    // Bail if invalid.
    if ( !m_valid || m_triangles.size() < 1 || !m_meshP )
    {
        return;
    }

    const V3f *points = m_meshP->get();
    const V3f *normals = NULL;
    if ( m_meshN  && ( m_meshN->size() == m_meshP->size() ) )
    {
        normals = m_meshN->get();
    }
    else if ( m_customN.size() == m_meshP->size() )
    {
        normals = &(m_customN.front());
    }

#ifndef SIMPLE_ABC_VIEWER_NO_GL_CLIENT_STATE
//#if 0
    {
        GL_NOISY( glEnableClientState( GL_VERTEX_ARRAY ) );
        if ( normals )
        {
            GL_NOISY( glEnableClientState( GL_NORMAL_ARRAY ) );
            GL_NOISY( glNormalPointer( GL_FLOAT, 0,
                                       ( const GLvoid * )normals ) );
        }

        GL_NOISY( glVertexPointer( 3, GL_FLOAT, 0,
                                   ( const GLvoid * )points ) );

        GL_NOISY( glDrawElements( GL_TRIANGLES,
                                  ( GLsizei )m_triangles.size() * 3,
                                  GL_UNSIGNED_INT,
                                  ( const GLvoid * )&(m_triangles[0]) ) );

        if ( normals )
        {
            GL_NOISY( glDisableClientState( GL_NORMAL_ARRAY ) );
        }
        GL_NOISY( glDisableClientState( GL_VERTEX_ARRAY ) );
    }
#else
    glBegin( GL_TRIANGLES );

    for ( size_t i = 0; i < m_triangles.size(); ++i )
    {
        const Tri &tri = m_triangles[i];
        const V3f &vertA = points[tri[0]];
        const V3f &vertB = points[tri[1]];
        const V3f &vertC = points[tri[2]];

        if ( normals )
        {
            const V3f &normA = normals[tri[0]];
            glNormal3fv( ( const GLfloat * )&normA );
            glVertex3fv( ( const GLfloat * )&vertA );

            const V3f &normB = normals[tri[1]];
            glNormal3fv( ( const GLfloat * )&normB );
            glVertex3fv( ( const GLfloat * )&vertB );

            const V3f &normC = normals[tri[2]];
            glNormal3fv( ( const GLfloat * )&normC );
            glVertex3fv( ( const GLfloat * )&vertC );
        }
        else
        {
            V3f AB = vertB - vertA;
            V3f AC = vertC - vertA;
            V3f N = AB.cross( AC );
            if ( N.length() > 1.0e-4f )
            {
                N.normalize();
                glNormal3fv( ( const GLfloat * )&N );
            }

            glVertex3fv( ( const GLfloat * )&vertA );

            glVertex3fv( ( const GLfloat * )&vertB );

            glVertex3fv( ( const GLfloat * )&vertC );
        }

    }

    glEnd();

#endif
}
Ejemplo n.º 9
0
std::pair<PrimitiveVariable, PrimitiveVariable> IECoreScene::MeshAlgo::calculateTangents(
	const MeshPrimitive *mesh,
	const std::string &uvSet, /* = "uv" */
	bool orthoTangents, /* = true */
	const std::string &position /* = "P" */
)
{
	if( mesh->minVerticesPerFace() != 3 || mesh->maxVerticesPerFace() != 3 )
	{
		throw InvalidArgumentException( "MeshAlgo::calculateTangents : MeshPrimitive must only contain triangles" );
	}

	const V3fVectorData *positionData = mesh->variableData<V3fVectorData>( position );
	if( !positionData )
	{
		std::string e = boost::str( boost::format( "MeshAlgo::calculateTangents : MeshPrimitive has no Vertex \"%s\" primitive variable." ) % position );
		throw InvalidArgumentException( e );
	}

	const V3fVectorData::ValueType &points = positionData->readable();

	const IntVectorData *vertsPerFaceData = mesh->verticesPerFace();
	const IntVectorData::ValueType &vertsPerFace = vertsPerFaceData->readable();

	const IntVectorData *vertIdsData = mesh->vertexIds();
	const IntVectorData::ValueType &vertIds = vertIdsData->readable();

	const auto uvIt = mesh->variables.find( uvSet );
	if( uvIt == mesh->variables.end() || uvIt->second.interpolation != PrimitiveVariable::FaceVarying || uvIt->second.data->typeId() != V2fVectorDataTypeId )
	{
		throw InvalidArgumentException( ( boost::format( "MeshAlgo::calculateTangents : MeshPrimitive has no FaceVarying V2fVectorData primitive variable named \"%s\"."  ) % ( uvSet ) ).str() );
	}

	const V2fVectorData *uvData = runTimeCast<V2fVectorData>( uvIt->second.data.get() );
	const V2fVectorData::ValueType &uvs = uvData->readable();

	// I'm a little unsure about using the vertIds as a fallback for the stIndices.
	const IntVectorData::ValueType &uvIndices = uvIt->second.indices ? uvIt->second.indices->readable() : vertIds;

	size_t numUVs = uvs.size();

	std::vector<V3f> uTangents( numUVs, V3f( 0 ) );
	std::vector<V3f> vTangents( numUVs, V3f( 0 ) );
	std::vector<V3f> normals( numUVs, V3f( 0 ) );

	for( size_t faceIndex = 0; faceIndex < vertsPerFace.size(); faceIndex++ )
	{
		assert( vertsPerFace[faceIndex] == 3 );

		// indices into the facevarying data for this face
		size_t fvi0 = faceIndex * 3;
		size_t fvi1 = fvi0 + 1;
		size_t fvi2 = fvi1 + 1;
		assert( fvi2 < vertIds.size() );
		assert( fvi2 < uvIndices.size() );

		// positions for each vertex of this face
		const V3f &p0 = points[vertIds[fvi0]];
		const V3f &p1 = points[vertIds[fvi1]];
		const V3f &p2 = points[vertIds[fvi2]];

		// uv coordinates for each vertex of this face
		const V2f &uv0 = uvs[uvIndices[fvi0]];
		const V2f &uv1 = uvs[uvIndices[fvi1]];
		const V2f &uv2 = uvs[uvIndices[fvi2]];

		// compute tangents and normal for this face
		const V3f e0 = p1 - p0;
		const V3f e1 = p2 - p0;

		const V2f e0uv = uv1 - uv0;
		const V2f e1uv = uv2 - uv0;

		V3f tangent = ( e0 * -e1uv.y + e1 * e0uv.y ).normalized();
		V3f bitangent = ( e0 * -e1uv.x + e1 * e0uv.x ).normalized();

		V3f normal = ( p2 - p1 ).cross( p0 - p1 );
		normal.normalize();

		// and accumlate them into the computation so far
		uTangents[uvIndices[fvi0]] += tangent;
		uTangents[uvIndices[fvi1]] += tangent;
		uTangents[uvIndices[fvi2]] += tangent;

		vTangents[uvIndices[fvi0]] += bitangent;
		vTangents[uvIndices[fvi1]] += bitangent;
		vTangents[uvIndices[fvi2]] += bitangent;

		normals[uvIndices[fvi0]] += normal;
		normals[uvIndices[fvi1]] += normal;
		normals[uvIndices[fvi2]] += normal;

	}

	// normalize and orthogonalize everything
	for( size_t i = 0; i < uTangents.size(); i++ )
	{
		normals[i].normalize();

		uTangents[i].normalize();
		vTangents[i].normalize();

		// Make uTangent/vTangent orthogonal to normal
		uTangents[i] -= normals[i] * uTangents[i].dot( normals[i] );
		vTangents[i] -= normals[i] * vTangents[i].dot( normals[i] );

		uTangents[i].normalize();
		vTangents[i].normalize();

		if( orthoTangents )
		{
			vTangents[i] -= uTangents[i] * vTangents[i].dot( uTangents[i] );
			vTangents[i].normalize();
		}

		// Ensure we have set of basis vectors (n, uT, vT) with the correct handedness.
		if( uTangents[i].cross( vTangents[i] ).dot( normals[i] ) < 0.0f )
		{
			uTangents[i] *= -1.0f;
		}
	}

	// convert the tangents back to facevarying data and add that to the mesh
	V3fVectorDataPtr fvUD = new V3fVectorData();
	V3fVectorDataPtr fvVD = new V3fVectorData();

	std::vector<V3f> &fvU = fvUD->writable();
	std::vector<V3f> &fvV = fvVD->writable();
	fvU.resize( uvIndices.size() );
	fvV.resize( uvIndices.size() );

	for( unsigned i = 0; i < uvIndices.size(); i++ )
	{
		fvU[i] = uTangents[uvIndices[i]];
		fvV[i] = vTangents[uvIndices[i]];
	}

	PrimitiveVariable tangentPrimVar( PrimitiveVariable::FaceVarying, fvUD );
	PrimitiveVariable bitangentPrimVar( PrimitiveVariable::FaceVarying, fvVD );

	return std::make_pair( tangentPrimVar, bitangentPrimVar );
}
//-*****************************************************************************
void MeshDrwHelper::draw( const DrawContext & iCtx ) const
{

    // Bail if invalid.
    if ( !m_valid || m_triangles.size() < 1 || !m_meshP )
    {
        return;
    }

    const V3f *points = m_meshP->get();
    const V3f *normals = NULL;
    if ( m_meshN  && ( m_meshN->size() == m_meshP->size() ) )
    {
        normals = m_meshN->get();
    }
    else if ( m_customN.size() == m_meshP->size() )
    {
        normals = &(m_customN.front());
    }
    
    // colors
    const C4f *colors = NULL;
    if (m_colors.size() == m_meshP->size() )
    {
        colors = &(m_colors.front());

    }

    static MGLFunctionTable *gGLFT = NULL;
    if (gGLFT == NULL)
       gGLFT = MHardwareRenderer::theRenderer()->glFunctionTable();

    gGLFT->glBegin( MGL_TRIANGLES );

    for ( size_t i = 0; i < m_triangles.size(); ++i )
    {
        const Tri &tri = m_triangles[i];
        const V3f &vertA = points[tri[0]];
        const V3f &vertB = points[tri[1]];
        const V3f &vertC = points[tri[2]];

        if ( normals )
        {
            const V3f &normA = normals[tri[0]];
            gGLFT->glNormal3fv( ( const GLfloat * )&normA );
            gGLFT->glVertex3fv( ( const GLfloat * )&vertA );

            const V3f &normB = normals[tri[1]];
            gGLFT->glNormal3fv( ( const GLfloat * )&normB );
            gGLFT->glVertex3fv( ( const GLfloat * )&vertB );

            const V3f &normC = normals[tri[2]];
            gGLFT->glNormal3fv( ( const GLfloat * )&normC );
            gGLFT->glVertex3fv( ( const GLfloat * )&vertC );
        }
        else
        {
            V3f AB = vertB - vertA;
            V3f AC = vertC - vertA;
            V3f N = AB.cross( AC );
            if ( N.length() > 1.0e-4f )
            {
                N.normalize();
                gGLFT->glNormal3fv( ( const GLfloat * )&N );
            }

            gGLFT->glVertex3fv( ( const GLfloat * )&vertA );

            gGLFT->glVertex3fv( ( const GLfloat * )&vertB );

            gGLFT->glVertex3fv( ( const GLfloat * )&vertC );
        }

    }

    gGLFT->glEnd();

}