Beispiel #1
0
SimpleModel* loadModelSTL_binary(const char* filename, FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rb");
    char buffer[80];
    uint32_t faceCount;
    //Skip the header
    if (fread(buffer, 80, 1, f) != 1)
    {
        fclose(f);
        return NULL;
    }
    //Read the face count
    if (fread(&faceCount, sizeof(uint32_t), 1, f) != 1)
    {
        fclose(f);
        return NULL;
    }
    //For each face read:
    //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
    SimpleModel* m = new SimpleModel();
    m->volumes.push_back(SimpleVolume());
    SimpleVolume* vol = &m->volumes[0];
	if(vol == NULL)
	{
		fclose(f);
		return NULL;
	}

    for(unsigned int i=0;i<faceCount;i++)
    {
        if (fread(buffer, sizeof(float) * 3, 1, f) != 1)
        {
            fclose(f);
            return NULL;
        }
        float v[9];
        if (fread(v, sizeof(float) * 9, 1, f) != 1)
        {
            fclose(f);
            return NULL;
        }
        Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
        Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
        Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
        vol->addFace(v0, v1, v2);
        if (fread(buffer, sizeof(uint16_t), 1, f) != 1)
        {
            fclose(f);
            return NULL;
        }
    } 
    fclose(f);
    return m;
}
Beispiel #2
0
bool loadMeshSTL_binary(Mesh* mesh, const char* filename, FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rb");

    fseek(f, 0L, SEEK_END);
    long long file_size = ftell(f); //The file size is the position of the cursor after seeking to the end.
    rewind(f); //Seek back to start.
    size_t face_count = (file_size - 80 - sizeof(uint32_t)) / 50; //Subtract the size of the header. Every face uses exactly 50 bytes.

    char buffer[80];
    //Skip the header
    if (fread(buffer, 80, 1, f) != 1)
    {
        fclose(f);
        return false;
    }

    uint32_t reported_face_count;
    //Read the face count. We'll use it as a sort of redundancy code to check for file corruption.
    if (fread(&reported_face_count, sizeof(uint32_t), 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    if (reported_face_count != face_count)
    {
        logWarning("Face count reported by file (%s) is not equal to actual face count (%s). File could be corrupt!\n", std::to_string(reported_face_count).c_str(), std::to_string(face_count).c_str());
    }

    //For each face read:
    //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
    // Every Face is 50 Bytes: Normal(3*float), Vertices(9*float), 2 Bytes Spacer
    mesh->faces.reserve(face_count);
    mesh->vertices.reserve(face_count);
    for (unsigned int i = 0; i < face_count; i++)
    {
        if (fread(buffer, 50, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
        float *v= ((float*)buffer)+3;

        Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
        Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
        Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
        mesh->addFace(v0, v1, v2);
    }
    fclose(f);
    mesh->finish();
    return true;
}
Beispiel #3
0
void vtRoute::_CreateStruct(int iNode)
{
	vtUtilNode *node =  m_Nodes.GetAt(iNode);

	bool add = false;
	if (!node->m_pTrans)
	{
		vtUtilStruct *sobj = node->m_struct;
		if (!sobj)
			return;

		osg::Node *tower = sobj->m_pTower;
		if (tower)
		{
			node->m_pTrans = new vtTransform;
			vtString name;
			name.Format("RouteNode %d", iNode);
			node->m_pTrans->setName(name);
			node->m_pTrans->addChild(tower);
			add = true;
		}
	}

	// set orientation
	node->m_pTrans->Identity();
	node->m_pTrans->RotateLocal(FPoint3(0,1,0), node->dRadAzimuth);

	m_pTheTerrain->PlantModelAtPoint(node->m_pTrans, node->m_Point);

	if (add)
		m_pTheTerrain->AddNodeToStructGrid(node->m_pTrans);
}
Beispiel #4
0
vtMovGeode *CreateSimpleEarth(const vtString &strDataPath)
{
    // create simple texture-mapped sphere
    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::QUADS, VT_Normals | VT_TexCoords, 20*20*2);
    int res = 20;
    FPoint3 size(1.0f, 1.0f, 1.0f);
    mesh->CreateEllipsoid(FPoint3(0,0,0), size, res);

    // fix up the texture coordinates
    int numvtx = mesh->GetNumVertices();
    for (int i = 0; i < numvtx; i++)
    {
        FPoint2 coord;
        coord.y = 1.0f - ((float) i / (res * res));
        coord.x = 1.0f - ((float (i%res)) / res);
        mesh->SetVtxTexCoord(i, coord);
    }

    vtGeode *geode = new vtGeode;
    vtMovGeode *mgeom = new vtMovGeode(geode);
    mgeom->setName("GlobeGeom");

    vtMaterialArray *pMats = new vtMaterialArray;
    bool bCulling = false;
    bool bLighting = false;
    bool bTransp = false;
    pMats->AddTextureMaterial2(strDataPath + "WholeEarth/earth2k_free.jpg",
                               bCulling, bLighting, bTransp);
    geode->SetMaterials(pMats);

    geode->AddMesh(mesh, 0);

    return mgeom;
}
Beispiel #5
0
/**
 * Set the XY position of the sprite.  These are in world coordinates,
 *  unless this sprite is the child of a vtHUD, in which case they are
 *  pixel coordinates measured from the lower-left corner of the window.
 *
 * \param l Left.
 * \param t Top.
 * \param r Right.
 * \param b Bottom.
 * \param rot Rotation in radians.
 */
void vtImageSprite::SetPosition(float l, float t, float r, float b, float rot)
{
	if (!m_pMesh)	// safety check
		return;

	FPoint2 p[4];
	p[0].Set(l, b);
	p[1].Set(r, b);
	p[2].Set(r, t);
	p[3].Set(l, t);

	if (rot != 0.0f)
	{
		FPoint2 center((l+r)/2, (b+t)/2);
		for (int i = 0; i < 4; i++)
		{
			p[i] -= center;
			p[i].Rotate(rot);
			p[i] += center;
		}
	}

	for (int i = 0; i < 4; i++)
		m_pMesh->SetVtxPos(i, FPoint3(p[i].x, p[i].y, 0));

	m_pMesh->ReOptimize();
}
Beispiel #6
0
/*
 * Set the time for the globe.  The globe will orient itself to properly
 * reflect the indicate date and time, including seasonal shift of the
 * polar axis and time of day.
 *
 * \param time A time value (assumed to be Greenwich Mean Time).
 */
void vtIcoGlobe::SetTime(const vtTime &time)
{
    float second_of_day = (float) time.GetSecondOfDay();
    float fraction_of_day = second_of_day / (24 * 60 * 60);
    float rotation = fraction_of_day * PI2f;

    // match with actual globe
    rotation += PID2f;

    FMatrix4 tmp, m4;
    m4.Identity();

    if (m_bTilt)
    {
        FPoint3 xvector(1,0,0), seasonal_axis;

        // Seasonal axis rotation (days since winter solstice, approximate)
        float season = (time.GetTM().tm_yday + 10) / 365.0f * PI2f;
        tmp.AxisAngle(FPoint3(0,1,0), season);
        tmp.Transform(xvector, seasonal_axis);

        // The earth's axis is tilted with respect to the plane of its orbit
        // at an angle of about 23.4 degrees.  Tilting the northern
        // hemisphere away from the sun (-tilt) puts this at the winter
        // solstice.
        float tilt = 23.4 / 180.0f * PIf;
        tmp.AxisAngle(seasonal_axis, -tilt);
        m4.PreMult(tmp);
    }

    // rotation around axis
    tmp.AxisAngle(FPoint3(0,1,0), rotation);
    m4.PreMult(tmp);

    // store rotation to a quaternion
    FMatrix3 m3 = m4;
    m_Rotation.SetFromMatrix(m3);

    // don't do time rotation on unfolded(ing) globes
    if (!m_bUnfolded)
        m_top->SetTransform1(m4);
}
Beispiel #7
0
//
// A single thin strip polygon with a single texture.
//
void vtFence3d::AddFlatConnectionMesh(const FLine3 &p3)
{
	vtMesh *pMesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_STRIP, VT_TexCoords, 100);

	vtMaterialDescriptor *desc = GetMatDescriptor(m_Params.m_ConnectMaterial);
	if (!desc)
	{
		VTLOG1("Warning: could not find material:");
		VTLOG1(m_Params.m_ConnectMaterial);
		VTLOG1("\n");
		return;
	}

	FPoint2 uvscale = desc->GetUVScale();

	float u = 0.0f;
	float vertical_meters = m_Params.m_fConnectTop - m_Params.m_fConnectBottom;
	float v_top;
	if (uvscale.y == -1)
		v_top = 1.0f;
	else
		v_top = vertical_meters / uvscale.y;

	uint i, npoints = p3.GetSize();
	int vidx = 0;
	for (i = 0; i < npoints; i++)
	{
		pMesh->SetVtxPUV(vidx++, p3[i] + FPoint3(0, m_Params.m_fConnectBottom, 0), u, 0.0);
		pMesh->SetVtxPUV(vidx++, p3[i] + FPoint3(0, m_Params.m_fConnectTop, 0), u, v_top);

		if (i < npoints-1)
		{
			// increment u based on the length of each fence segment
			float length_meters = (p3[i+1] - p3[i]).Length();
			u += (length_meters / desc->GetUVScale().x);
		}
	}
	pMesh->AddStrip2(npoints * 2, 0);

	m_pFenceGeom->AddMesh(pMesh, GetMatIndex(desc));
}
Beispiel #8
0
//
// stoplights and stopsigns
//
void vtRoadMap3d::GenerateSigns(vtLodGrid *pLodGrid)
{
	if (!pLodGrid)
		return;

	vtContentManager3d &con = vtGetContent();
	osg::Node *stopsign = con.CreateNodeFromItemname("American Stopsign");
	osg::Node *stoplight = con.CreateNodeFromItemname("Stoplight (right)");

	if (!stopsign || !stoplight)
	{
		VTLOG("Couldn't find stopsign and stoplight.\n");
		return;
	}
	for (NodeGeom *pN = GetFirstNode(); pN; pN = pN->GetNext())
	{
		for (int r = 0; r < pN->NumLinks(); r++)
		{
			osg::Node *shape = NULL;
			if (pN->GetIntersectType(r) == IT_STOPSIGN && stopsign)
			{
				shape = (osg::Node *) stopsign->clone(osg::CopyOp::SHALLOW_COPY);
			}
			if (pN->GetIntersectType(r) == IT_LIGHT && stoplight)
			{
				shape = (osg::Node *) stoplight->clone(osg::CopyOp::SHALLOW_COPY);
			}
			if (!shape) continue;

			vtTransform *trans = new vtTransform;
			trans->addChild(shape);

			LinkGeom *link = pN->GetLink(r);
			FPoint3 unit = pN->GetUnitLinkVector(r);
			FPoint3 perp(unit.z, unit.y, -unit.x);
			FPoint3 offset;

			// Turn the sign (yaw) to face the oncoming traffic
			trans->RotateLocal(FPoint3(0,1,0), pN->GetLinkAngle(r) + PID2f);

			if (pN->GetIntersectType(r) == IT_STOPSIGN)
			{
				offset = pN->m_p3 + (unit * 6.0f) + (perp * (link->m_fRightWidth));
			}
			if (pN->GetIntersectType(r) == IT_LIGHT)
			{
				offset = pN->m_p3 - (unit * 6.0f) + (perp * (link->m_fRightWidth));
			}
			trans->Translate(offset);
			pLodGrid->AddToGrid(trans);
		}
	}
}
Beispiel #9
0
void LayerDlg::OnZoomTo( wxCommandEvent &event )
{
	VTLOG1("LayerDlg::OnZoomTo\n");

	osg::Node *pThing = GetNodeFromItem(m_item, true);	// get container
	if (pThing)
	{
		FSphere sphere = GetGlobalBoundSphere(pThing);   // get global bounds
		vtCamera *pCam = vtGetScene()->GetCamera();

		// Put the camera a bit back from the sphere; sufficiently so that
		//  the whole volume of the bounding sphere is visible.
		float smallest = min(pCam->GetFOV(), pCam->GetVertFOV());
		float alpha = smallest / 2.0f;
		float distance = sphere.radius / tanf(alpha);
		pCam->Identity();
		pCam->Rotate(FPoint3(1,0,0), -PID2f/2);	// tilt down a little
		pCam->Translate(sphere.center);
		pCam->TranslateLocal(FPoint3(0.0f, 0.0f, distance));
	}
}
Beispiel #10
0
bool loadMeshSTL_binary(Mesh* mesh, const char* filename, FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rb");
    char buffer[80];
    uint32_t faceCount;
    //Skip the header
    if (fread(buffer, 80, 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    //Read the face count
    if (fread(&faceCount, sizeof(uint32_t), 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    //For each face read:
    //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
    // Every Face is 50 Bytes: Normal(3*float), Vertices(9*float), 2 Bytes Spacer
    mesh->faces.reserve(faceCount);
    mesh->vertices.reserve(faceCount);
    for(unsigned int i=0;i<faceCount;i++)
    {
        if (fread(buffer, 50, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
        float *v= ((float*)buffer)+3;

        Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
        Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
        Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
        mesh->addFace(v0, v1, v2);
    }
    fclose(f);
    mesh->finish();
    return true;
}
Beispiel #11
0
/**
 * Create a vtImageSprite.
 *
 * \param pImage A texture image.
 * \param bBlending Set to true for alpha-blending, which produces smooth
 *		edges on transparent textures.
 */
bool vtImageSprite::Create(osg::Image *pImage, bool bBlending)
{
	m_Size.x = GetWidth(pImage);
	m_Size.y = GetHeight(pImage);

	// set up material and geometry container
	m_pMats = new vtMaterialArray;
	m_pGeode = new vtGeode;
	m_pGeode->SetMaterials(m_pMats);

	m_pMats->AddTextureMaterial(pImage, false, false, bBlending);

	// default position of the mesh is just 0,0-1,1
	m_pMesh = new vtMesh(osg::PrimitiveSet::QUADS, VT_TexCoords, 4);
	m_pMesh->AddVertexUV(FPoint3(0,0,0), FPoint2(0,0));
	m_pMesh->AddVertexUV(FPoint3(1,0,0), FPoint2(1,0));
	m_pMesh->AddVertexUV(FPoint3(1,1,0), FPoint2(1,1));
	m_pMesh->AddVertexUV(FPoint3(0,1,0), FPoint2(0,1));
	m_pMesh->AddQuad(0, 1, 2, 3);
	m_pGeode->AddMesh(m_pMesh, 0);
	return true;
}
Beispiel #12
0
void GlobePicker::Eval()
{
    FPoint3 pos, dir;

    vtGetScene()->CameraRay(m_pos, pos, dir);

    // test whether we hit the globe
    FSphere sphere(FPoint3(0.0f, 0.0f, 0.0f), (float)m_fRadius);
    FPoint3 akPoint[2];
    int riQuantity;

    m_bOnTerrain = RaySphereIntersection(pos, dir, sphere, riQuantity, akPoint);
    if (m_bOnTerrain)
    {
        // save result
        m_GroundPoint = akPoint[0];

        // apply global position to target (which is not a child of the globe)
        vtTransform *pTarget = (vtTransform *) GetTarget();
        if (pTarget)
        {
            pTarget->Identity();
            pTarget->SetTrans(m_GroundPoint);
            pTarget->PointTowards(m_GroundPoint * 2.0f);
            pTarget->Scale(m_fTargetScale);
        }

        if (m_pGlobe)
        {
            // rotate to find position relative to globe's rotation
            vtTransform *xform = m_pGlobe->GetTop();
            FMatrix4 rot;
            xform->GetTransform1(rot);
            FMatrix4 inverse;
            inverse.Invert(rot);
            FPoint3 newpoint;

            // work around SML bug: matrices flagged as identity but
            // will still transform by their components
            if (! inverse.IsIdentity())
            {
                inverse.Transform(m_GroundPoint, newpoint);
                m_GroundPoint = newpoint;
            }
        }

        // Find corresponding geographic coordinates
        xyz_to_geo(m_fRadius, m_GroundPoint, m_EarthPos);
    }
}
Beispiel #13
0
void vtIcoGlobe::BuildFlatPoint(GlobeLayer *glay, int i, float fSize)
{
    vtFeatureSet *feat = glay->m_pSet;
    vtFeatureSetPoint2D *pSetP2 = dynamic_cast<vtFeatureSetPoint2D*>(feat);
    if (!pSetP2)
        return;

    // create and place the geometries
    DPoint2 p;
    int face, subface;
    DPoint3 p_out;

    pSetP2->GetPoint(i, p);

    if (p.x == 0.0 && p.y == 0.0)	// ignore some
        return;

    FPoint3 offset;
    GeoToFacePoint(p, face, subface, p_out);

    int mface = GetMFace(face, subface);

    p_out -= m_mface[mface].local_origin;

    vtGeode *geode = new vtGeode;
    geode->SetMaterials(m_coremats);
    geode->AddMesh(m_cylinder, m_yellow);

    vtMovGeode *mgeom = new vtMovGeode(geode);
    mgeom->setName("GlobeShape");

//	mgeom->RotateLocal(FPoint3(1,0,0), -PID2f);
    DPoint3 v0 = m_verts[icosa_face_v[face][0]];
    DPoint3 v1 = m_verts[icosa_face_v[face][1]];
    DPoint3 v2 = m_verts[icosa_face_v[face][2]];
    DPoint3 facenorm = (v0 + v1 + v2).Normalize();

    mgeom->PointTowards(facenorm);
    mgeom->RotateLocal(FPoint3(1,0,0), -PID2f);

    mgeom->SetTrans(p_out);

    // scale just the radius of the cylinder
    mgeom->Scale3(fSize, 0.001f, fSize);

    m_mface[mface].surfgroup->addChild(mgeom);
    glay->addChild(mgeom);
}
Beispiel #14
0
void AdaptiveLayerHeights::calculateMeshTriangleSlopes()
{
    // loop over all mesh faces (triangles) and find their slopes
    for (const Mesh& mesh : Application::getInstance().current_slice->scene.current_mesh_group->meshes)
    {
        // Skip meshes that are not printable
        if (mesh.settings.get<bool>("infill_mesh") || mesh.settings.get<bool>("cutting_mesh") || mesh.settings.get<bool>("anti_overhang_mesh"))
        {
            continue;
        }

        for (const MeshFace& face : mesh.faces)
        {
            const MeshVertex& v0 = mesh.vertices[face.vertex_index[0]];
            const MeshVertex& v1 = mesh.vertices[face.vertex_index[1]];
            const MeshVertex& v2 = mesh.vertices[face.vertex_index[2]];

            const FPoint3 p0 = v0.p;
            const FPoint3 p1 = v1.p;
            const FPoint3 p2 = v2.p;

            float min_z = p0.z;
            min_z = std::min(min_z, p1.z);
            min_z = std::min(min_z, p2.z);
            float max_z = p0.z;
            max_z = std::max(max_z, p1.z);
            max_z = std::max(max_z, p2.z);

            // calculate the angle of this triangle in the z direction
            const FPoint3 n = FPoint3(p1 - p0).cross(p2 - p0);
            const FPoint3 normal = n.normalized();
            AngleRadians z_angle = std::acos(std::abs(normal.z));

            // prevent flat surfaces from influencing the algorithm
            if (z_angle == 0)
            {
                z_angle = M_PI;
            }

            face_min_z_values.push_back(min_z * 1000);
            face_max_z_values.push_back(max_z * 1000);
            face_slopes.push_back(z_angle);
        }
    }
}
Beispiel #15
0
void vtJoystickEngine::Eval()
{
	if (!m_pStick)
		return;

	float fTime = vtGetTime(), fElapsed = fTime - m_fLastTime;

	vtTransform *pTarget = (vtTransform*) GetTarget();
	if (pTarget)
	{
		wxPoint p = m_pStick->GetPosition();
		int buttons = m_pStick->GetButtonState();
		float dx = ((float)p.x / 32768) - 1.0f;
		float dy = ((float)p.y / 32768) - 1.0f;

		// use a small dead zone to avoid drift
		const float dead_zone = 0.04f;

		if (buttons & wxJOY_BUTTON2)
		{
			// move up down left right
			if (fabs(dx) > dead_zone)
				pTarget->TranslateLocal(FPoint3(dx * m_fSpeed * fElapsed, 0.0f, 0.0f));
			if (fabs(dy) > dead_zone)
				pTarget->Translate(FPoint3(0.0f, dy * m_fSpeed * fElapsed, 0.0f));
		}
		else if (buttons & wxJOY_BUTTON3)
		{
			// pitch up down, yaw left right
			if (fabs(dx) > dead_zone)
				pTarget->RotateParent(FPoint3(0,1,0), -dx * fElapsed);
			if (fabs(dy) > dead_zone)
				pTarget->RotateLocal(FPoint3(1,0,0), dy * fElapsed);
		}
		else
		{
			// move forward-backward, turn left-right
			if (fabs(dy) > dead_zone)
				pTarget->TranslateLocal(FPoint3(0.0f, 0.0f, dy * m_fSpeed * fElapsed));
			if (fabs(dx) > dead_zone)
				pTarget->RotateParent(FPoint3(0,1,0), -dx * fElapsed);
		}
	}
	m_fLastTime = fTime;
}
Beispiel #16
0
//
// Create a moveable wireframe axis geometry.
//
vtTransform *WireAxis(RGBf color, float len)
{
    vtGeode *geode = new vtGeode;
    geode->setName("axis");

    vtMaterialArray *pMats = new vtMaterialArray;
    int index = pMats->AddRGBMaterial1(color, false, false);
    geode->SetMaterials(pMats);

    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::LINES, 0, 6);
    mesh->AddVertex(FPoint3(-len,0,0));
    mesh->AddVertex(FPoint3( len,0,0));
    mesh->AddVertex(FPoint3(0,-len,0));
    mesh->AddVertex(FPoint3(0, len,0));
    mesh->AddVertex(FPoint3(0,0,-len));
    mesh->AddVertex(FPoint3(0,0, len));
    mesh->AddLine(0,1);
    mesh->AddLine(2,3);
    mesh->AddLine(4,5);
    geode->AddMesh(mesh, index);
    vtTransform *trans = new vtTransform;
    trans->addChild(geode);
    return trans;
}
Beispiel #17
0
void vtFence3d::AddPostExtensions(const FLine3 &p3)
{
	uint i, j, npoints = p3.GetSize();

	bool bLeft = false, bRight = false, bWires = (npoints > 1);
	if (m_Params.m_PostExtension == "left")
		bLeft = true;
	if (m_Params.m_PostExtension == "right")
		bRight = true;
	if (m_Params.m_PostExtension == "double")
		bLeft = bRight = true;

	// create extension prism(s)
	vtMesh *pMesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_FAN, VT_Normals, 20);

	FPoint2 size(m_Params.m_fPostWidth, m_Params.m_fPostWidth);
	FPoint2 size1 = size * 0.9f;
	FPoint2 size2 = size * 0.5f;
	FPoint3 sideways, upward;

	float wire_height[3] = { 0.3f, 0.6f, 0.9f };

	vtMesh *pWiresLeft, *pWiresRight;
	if (bLeft && bWires)
		pWiresLeft = new vtMesh(osg::PrimitiveSet::LINE_STRIP, 0, npoints*3);
	if (bRight && bWires)
		pWiresRight = new vtMesh(osg::PrimitiveSet::LINE_STRIP, 0, npoints*3);

	for (i = 0; i < npoints; i++)
	{
		FPoint3 base = p3[i] + FPoint3(0.0f, m_Params.m_fPostHeight, 0.0f);

		// determine side-pointing normal
		if (i == 0)
			sideways = SidewaysVector(p3[i], p3[i+1]);
		else if (i > 0 && i < npoints-1)
		{
			AngleSideVector(p3[i-1], p3[i], p3[i+1], sideways);
			sideways = -sideways;	// We want a vector pointing left, not right
		}
		else if (i == npoints-1)
			sideways = SidewaysVector(p3[i-1], p3[i]);

		if (bLeft && bWires)
		{
			upward = -sideways + FPoint3(0,1,0);
			upward.SetLength(0.35);	// roughly 1 foot is standard
			pMesh->CreatePrism(base,
				upward, size1, size2);

			for (j = 0; j < 3; j++)
				pWiresLeft->SetVtxPos(j*npoints + i, base + upward * wire_height[j]);
		}
		if (bRight && bWires)
		{
			upward = sideways + FPoint3(0,1,0);
			upward.SetLength(0.35);	// roughly 1 foot is standard
			pMesh->CreatePrism(base, upward, size1, size2);

			for (j = 0; j < 3; j++)
				pWiresRight->SetVtxPos(j*npoints + i, base + upward * wire_height[j]);
		}
	}
	m_pFenceGeom->AddMesh(pMesh, GetMatIndex("Steel"));

	if (bLeft && bWires)
	{
		pWiresLeft->AddStrip2(npoints, 0);
		pWiresLeft->AddStrip2(npoints, npoints);
		pWiresLeft->AddStrip2(npoints, npoints*2);
		m_pFenceGeom->AddMesh(pWiresLeft, GetMatIndex("Wire"));
	}
	if (bRight && bWires)
	{
		pWiresRight->AddStrip2(npoints, 0);
		pWiresRight->AddStrip2(npoints, npoints);
		pWiresRight->AddStrip2(npoints, npoints*2);
		m_pFenceGeom->AddMesh(pWiresRight, GetMatIndex("Wire"));
	}
}
Beispiel #18
0
/*!
Returns the index of the 'other' face connected to the edge between vertices with indices idx0 and idx1.
In case more than two faces are connected via the same edge, the next face in a counter-clockwise ordering (looking from idx1 to idx0) is returned.

\cond DOXYGEN_EXCLUDE
    [NON-RENDERED COMENTS]
    For two faces abc and abd with normals n and m, we have that:
    \f{eqnarray*}{
    n &=& \frac{ab \times ac}{\|ab \times ac\|}     \\
    m &=& \frac{ab \times ad}{\|ab \times ad\|}     \\
    n \times m &=& \|n\| \cdot \|m\| \mathbf{p} \sin \alpha  \\
    && (\mathbf{p} \perp n \wedge \mathbf{p} \perp m) \\
    \sin \alpha &=& \|n \times m \|
    &=& \left\| \frac{(ab \times ac) \times (ab \times ad)}{\|ab \times ac\| \cdot \|ab \times ad\|}  \right\|    \\
    &=& \left\| \frac{ (ab \cdot (ac \times ad)) ab  }{\|ab \times ac\| \cdot \|ab \times ad\|}  \right\|    \\
    &=&  \frac{ (ab \cdot (ac \times ad)) \left\| ab   \right\| }{\|ab\| \|ac\| \sin bac \cdot \|ab\| \|ad\| \sin bad}    \\
    &=&  \frac{  ab \cdot (ac \times ad)  }{\|ab\| \|ac\| \|ad\|  \sin bac \sin bad}    \\
    \f}}
\endcond

See <a href="http://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors">Direct way of computing clockwise angle between 2 vectors</a>


*/
int Mesh::getFaceIdxWithPoints(int idx0, int idx1, int notFaceIdx) const
{
    std::vector<int> candidateFaces; // in case more than two faces meet at an edge, multiple candidates are generated
    int notFaceVertexIdx = -1; // index of the third vertex of the face corresponding to notFaceIdx
    for(int f : vertices[idx0].connected_faces) // search through all faces connected to the first vertex and find those that are also connected to the second
    {
        if (f == notFaceIdx)
        {
            for (int i = 0; i<3; i++) // find the vertex which is not idx0 or idx1
                if (faces[f].vertex_index[i] != idx0 && faces[f].vertex_index[i] != idx1)
                    notFaceVertexIdx = faces[f].vertex_index[i];
            continue;
        }
        if ( faces[f].vertex_index[0] == idx1 // && faces[f].vertex_index[1] == idx0 // next face should have the right direction!
          || faces[f].vertex_index[1] == idx1 // && faces[f].vertex_index[2] == idx0
          || faces[f].vertex_index[2] == idx1 // && faces[f].vertex_index[0] == idx0
            )  candidateFaces.push_back(f);

    }

    if (candidateFaces.size() == 0) { cura::logError("Couldn't find face connected to face %i.\n", notFaceIdx); return -1; }
    if (candidateFaces.size() == 1) { return candidateFaces[0]; }


    if (notFaceVertexIdx < 0) { cura::logError("Couldn't find third point on face %i.\n", notFaceIdx); return -1; }

    if (candidateFaces.size() % 2 == 0) cura::log("Warning! Edge with uneven number of faces connecting it!(%i)\n", candidateFaces.size()+1);

    FPoint3 vn = vertices[idx1].p - vertices[idx0].p;
    FPoint3 n = vn / vn.vSize(); // the normal of the plane in which all normals of faces connected to the edge lie => the normalized normal
    FPoint3 v0 = vertices[idx1].p - vertices[idx0].p;

// the normals below are abnormally directed! : these normals all point counterclockwise (viewed from idx1 to idx0) from the face, irrespective of the direction of the face.
    FPoint3 n0 = FPoint3(vertices[notFaceVertexIdx].p - vertices[idx0].p).cross(v0);

    if (n0.vSize() <= 0) cura::log("Warning! Face %i has zero area!", notFaceIdx);

    double smallestAngle = 1000; // more then 2 PI (impossible angle)
    int bestIdx = -1;

    for (int candidateFace : candidateFaces)
    {
        int candidateVertex;
        {// find third vertex belonging to the face (besides idx0 and idx1)
            for (candidateVertex = 0; candidateVertex<3; candidateVertex++)
                if (faces[candidateFace].vertex_index[candidateVertex] != idx0 && faces[candidateFace].vertex_index[candidateVertex] != idx1)
                    break;
        }

        FPoint3 v1 = vertices[candidateVertex].p -vertices[idx0].p;
        FPoint3 n1 = v1.cross(v0);

        double dot = n0 * n1;
        double det = n * n0.cross(n1);
        double angle = std::atan2(det, dot);
        if (angle < 0) angle += 2*M_PI; // 0 <= angle < 2* M_PI

        if (angle == 0)
        {
            cura::log("Warning! Overlapping faces: face %i and face %i.\n", notFaceIdx, candidateFace);
            std::cerr<< n.vSize() <<"; "<<n1.vSize()<<";"<<n0.vSize() <<std::endl;
        }
        if (angle < smallestAngle)
        {
            smallestAngle = angle;
            bestIdx = candidateFace;
        }
    }
    if (bestIdx < 0) cura::logError("Couldn't find face connected to face %i.\n", notFaceIdx);
    return bestIdx;
}
Beispiel #19
0
bool vtContourConverter::SetupTerrain(vtTerrain *pTerr)
{
	// Make a note of this terrain and its attributes
	m_pTerrain = pTerr;
	m_pHF = pTerr->GetHeightFieldGrid3d();
	int tileLod0Size = 0;
	if (!m_pHF)
	{
		vtTiledGeom *tiledGeom = pTerr->GetTiledGeom();
		if (!tiledGeom)
			return false;

		m_ext = tiledGeom->GetEarthExtents();
		//get highest LOD
		int minLod = 0;
		for(int i = 0; i < tiledGeom->rows * tiledGeom->rows; i++)
			if (tiledGeom->m_elev_info.lodmap.m_min[i] > minLod)
				minLod = tiledGeom->m_elev_info.lodmap.m_min[i];

		tileLod0Size = 1 << minLod;
		m_spacing = DPoint2(m_ext.Width() / (tiledGeom->cols * tileLod0Size), m_ext.Height() / (tiledGeom->rows *tileLod0Size));
	}
	else
	{
		m_ext = m_pHF->GetEarthExtents();
		m_spacing = m_pHF->GetSpacing();
	}

	// copy data from our grid to a QuikGrid object
	int nx, ny;
	if (m_pHF)
		m_pHF->GetDimensions(nx, ny);
	else
	{
		vtTiledGeom *tiledGeom = pTerr->GetTiledGeom();
		nx = tiledGeom->cols * tileLod0Size + 1;
		ny = tiledGeom->rows * tileLod0Size + 1;
	}
	// we can't allocate too much memory, so reduce the resolution if too large
	DPoint2 scale(1.0, 1.0);
	while ((nx/scale.x) > 8192)
		scale.x *= 2.0;
	while ((ny/scale.y) > 8192)
		scale.y *= 2.0;

	m_spacing.x *= scale.x;
	m_spacing.y *= scale.y;
	nx /= scale.x;
	ny /= scale.y;

	m_pGrid = new SurfaceGrid(nx,ny);
	int i, j;
	if (m_pHF)
	{
		for (i = 0; i < nx; i++)
		{
			for (j = 0; j < ny; j++)
			{
				// use the true elevation, for true contours
				m_pGrid->zset(i, j, m_pHF->GetElevation(i, j, true));
			}
		}
	}
	else
	{
		vtTiledGeom *tiledGeom = pTerr->GetTiledGeom();
		float topBottom = tiledGeom->m_WorldExtents.top - tiledGeom->m_WorldExtents.bottom;
		float rightLeft = tiledGeom->m_WorldExtents.right - tiledGeom->m_WorldExtents.left;
		float xwidth = rightLeft / nx;
		float ywidth = topBottom / ny;
		float altitude;
		for (i = 0; i < nx; i++)
		{
			for (j = 0; j < ny; j++)
			{
				// use the true elevation, for true contours
				tiledGeom->FindAltitudeAtPoint(FPoint3(i*xwidth, 0, j*ywidth),altitude, true);
				m_pGrid->zset(i, j, altitude);
			}
		}
	}
	return true;
}
Beispiel #20
0
void vtRoadMap3d::SetHeightOffGround(float fHeight)
{
	m_fGroundOffset = fHeight;
	if (m_pTransform)
		m_pTransform->SetTrans(FPoint3(0, m_fGroundOffset, 0));
}
Beispiel #21
0
void vtIcoGlobe::BuildSphericalPoints(GlobeLayer *glay, float fSize)
{
    vtFeatureSet *feat = glay->m_pSet;
    int i, j, size;
    vtArray<FSphere> spheres;

    size = feat->GetNumEntities();
    spheres.SetSize(size);

    vtFeatureSetPoint2D *pSetP2 = dynamic_cast<vtFeatureSetPoint2D*>(feat);
    if (!pSetP2)
        return;

    DPoint2 p;
    for (i = 0; i < size; i++)
    {
        pSetP2->GetPoint(i, p);

        if (p.x == 0.0 && p.y == 0.0)	// ignore some
            continue;

        FPoint3 loc;
        geo_to_xyz(1.0, p, loc);

        spheres[i].center = loc;
        spheres[i].radius = fSize;
    }

    FPoint3 diff;

    // volume of sphere, 4/3 PI r^3
    // surface area of sphere, 4 PI r^2
    // area of circle of sphere as seen from distance, PI r^2
    int merges;
    do {
        merges = 0;
        // Try merging overlapping points together, so that information
        // is not lost in the overlap.
        // To consider: do we combine the blobs based on their 2d radius,
        // their 2d area, their 3d radius, or their 3d volume?  See
        // Tufte, http://www.edwardtufte.com/
        // Implemented here: preserve 2d area
        for (i = 0; i < size-1; i++)
        {
            for (j = i+1; j < size; j++)
            {
                if (spheres[i].radius == 0.0f || spheres[j].radius == 0.0f)
                    continue;

                diff = spheres[i].center - spheres[j].center;

                // if one sphere contains the center of the other
                if (diff.Length() < spheres[i].radius ||
                        diff.Length() < spheres[j].radius)
                {
                    // combine
                    float area1 = PIf * spheres[i].radius * spheres[i].radius;
                    float area2 = PIf * spheres[j].radius * spheres[j].radius;
                    float combined = (area1 + area2);
                    float newrad = sqrtf( combined / PIf );
                    // larger eats the smaller
                    if (area1 > area2)
                    {
                        spheres[i].radius = newrad;
                        spheres[j].radius = 0.0f;
                    }
                    else
                    {
                        spheres[j].radius = newrad;
                        spheres[i].radius = 0.0f;
                    }
                    merges++;
                    break;
                }
            }
        }
    }
    while (merges != 0);

    // Now create and place the little geometry objects to represent the
    // point data.

#if 0
    // create simple hemisphere mesh
    int res = 6;
    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_STRIP, 0, res*res*2);
    FPoint3 scale(1.0f, 1.0f, 1.0f);
    mesh->CreateEllipsoid(scale, res, true);
#else
    // create cylinder mesh instead
    int res = 14;
    int verts = res * 2;
    vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLE_STRIP, 0, verts);
    mesh->CreateCylinder(1.0f, 1.0f, res, true, false, false);
#endif

    // use Area to show amount, otherwise height
    bool bArea = true;

    // create and place the geometries
    size = spheres.GetSize();
    for (i = 0; i < size; i++)
    {
        if (spheres[i].radius == 0.0f)
            continue;

        vtGeode *geode = new vtGeode;
        geode->SetMaterials(m_coremats);
        geode->AddMesh(mesh, m_yellow);

        vtMovGeode *mgeom = new vtMovGeode(geode);
        mgeom->setName("GlobeShape");

        mgeom->PointTowards(spheres[i].center);
        mgeom->RotateLocal(FPoint3(1,0,0), -PID2f);
        mgeom->SetTrans(spheres[i].center);
        if (bArea)
        {
            // scale just the radius of the cylinder
            mgeom->Scale3(spheres[i].radius, 0.001f, spheres[i].radius);
        }
        else
        {
            // scale just the height of the cylinder
            double area = PIf * spheres[i].radius * spheres[i].radius;
            mgeom->Scale3(0.002f, (float)area*1000, 0.002f);
        }
        m_SurfaceGroup->addChild(mgeom);
        glay->addChild(mgeom);
    }
}
Beispiel #22
0
vtTransform *vtRoadMap3d::GenerateGeometry(bool do_texture,
	bool bHwy, bool bPaved, bool bDirt, bool progress_callback(int))
{
	VTLOG("   vtRoadMap3d::GenerateGeometry\n");
	VTLOG("   Nodes %d, Links %d\n", NumNodes(), NumLinks());

	_CreateMaterials(do_texture);

	m_pGroup = new vtGroup;
	m_pGroup->setName("Roads");

	m_pTransform = new vtTransform;
	m_pTransform->addChild(m_pGroup);
	m_pTransform->SetTrans(FPoint3(0, m_fGroundOffset, 0));

	// We wrap the roads' geometry with an array of simple LOD nodes
	int a, b;
	for (a = 0; a < ROAD_CLUSTER; a++)
		for (b = 0; b < ROAD_CLUSTER; b++)
		{
			m_pRoads[a][b] = NULL;
		}

	_GatherExtents();

#if 0
	vtGeode *pGeode = CreateLineGridGeom(m_pMats, 0,
						   m_extents.min, m_extents.max, ROAD_CLUSTER);
	m_pGroup->addChild(pGeode);
#endif

	vtMesh *pMesh;
	int count = 0, total = NumLinks() + NumNodes();
	for (LinkGeom *pL = GetFirstLink(); pL; pL = pL->GetNext())
	{
		// Decide whether to construct this link
		bool include = false;
		if (bHwy && bPaved && bDirt)
			include = true;
		else
		{
			bool bIsDirt = (pL->m_Surface == SURFT_2TRACK || pL->m_Surface == SURFT_DIRT);
			if (bHwy && pL->m_iHwy != -1)
				include = true;
			if (bPaved && !bIsDirt)
				include = true;
			if (bDirt && bIsDirt)
				include = true;
		}
		if (include)
			pL->GenerateGeometry(this);
		count++;
		if (progress_callback != NULL)
			progress_callback(count * 100 / total);
	}
	count = 0;
	for (NodeGeom *pN = GetFirstNode(); pN; pN = pN->GetNext())
	{
		// What material to use?  We used to simply use "pavement", but that is
		// bad when they are e.g. trail or stone.  Now, we will try to guess
		// what to use by looking at the links here.
		int node_vti = VTI_PAVEMENT;
		for (int i = 0; i < pN->NumLinks(); i++)
		{
			LinkGeom *pL = pN->GetLink(i);
			switch (pL->m_vti)
			{
			case VTI_RAIL:
			case VTI_4WD:
			case VTI_TRAIL:
			case VTI_GRAVEL:
			case VTI_STONE:
				node_vti = pL->m_vti;
			}
		}
		VirtualTexture &vt = m_vt[node_vti];

		pMesh = pN->GenerateGeometry(vt);
		if (pMesh)
			AddMeshToGrid(pMesh, vt.m_idx);
		count++;
		if (progress_callback != NULL)
			progress_callback(count * 100 / total);
	}

	// return the top group, ready to be added to scene graph
	return m_pTransform;
}
Beispiel #23
0
void vtIcoGlobe::CreateUnfoldableDymax()
{
    int i;
    for (i = 0; i < 22; i++)
    {
        m_mface[i].xform = new vtTransform;
        m_mface[i].surfgroup = new vtGroup;
        m_mface[i].surfgroup->SetEnabled(false);
        m_mface[i].geode = new vtGeode;
        m_mface[i].xform->addChild(m_mface[i].geode);
        m_mface[i].xform->addChild(m_mface[i].surfgroup);

        vtString str;
        str.Format("IcoFace %d", i);
        m_mface[i].xform->setName(str);

        int face = dymax_subfaces[i].face;
        int subfaces = dymax_subfaces[i].subfaces;

        bool which;
        int mat = GetMaterialForFace(face, which);

        add_face2(m_mesh[i], face, i, subfaces, which);

        m_mface[i].geode->SetMaterials(m_earthmats);
        m_mface[i].geode->AddMesh(m_mesh[i], m_globe_mat[mat]);
    }
    m_top->addChild(m_mface[0].xform);

    m_mface[0].local_origin.Set(0,0,0);
    for (i = 1; i < 22; i++)
        FindLocalOrigin(i);
    for (i = 1; i < 22; i++)
        SetMeshConnect(i);

    // Determine necessary rotation to orient flat map toward viewer.
    FQuat qface;
    DPoint3 v0 = m_verts[icosa_face_v[0][0]];
    DPoint3 v1 = m_verts[icosa_face_v[0][1]];
    DPoint3 v2 = m_verts[icosa_face_v[0][2]];

    // Create a rotation to turn the globe so that a specific edge
    //  is pointed down -X for proper map orientation
    DPoint3 edge = v2 - v0;
    edge.Normalize();

    // compose face norm and face quaternion
    DPoint3 fnorm = (v0 + v1 + v2).Normalize();
    qface.SetFromVectors(edge, fnorm);

    // desired vector points down -X
    FQuat qdesired;
    qdesired.SetFromVectors(FPoint3(-1,0,0),FPoint3(0,0,1));

    // determine rotational difference
    m_diff = qface.Inverse() * qdesired;

#if 0
    // scaffolding mesh for debugging
    vtMesh *sm = new vtMesh(GL_LINES, VT_Colors, 12);
    sm->AddVertex(v0*1.0001f);
    sm->AddVertex(v1*1.0001f);
    sm->AddVertex(v2*1.0001f);
    sm->AddVertex(v0*1.0001f+fnorm);
    sm->SetVtxColor(0, RGBf(1,0,0));
    sm->SetVtxColor(1, RGBf(0,1,0));
    sm->SetVtxColor(2, RGBf(0,0,1));
    sm->SetVtxColor(3, RGBf(1,1,0));
    sm->AddLine(0,1);
    sm->AddLine(0,2);
    sm->AddLine(0,3);
    m_geom[0]->AddMesh(sm, m_red);
    sm->Release();
#endif

    // Show axis of rotation (north and south poles)
    vtMaterialArray *pMats = new vtMaterialArray;
    int green = pMats->AddRGBMaterial1(RGBf(0,1,0), false, false);
    m_pAxisGeom = new vtGeode;
    m_pAxisGeom->setName("AxisGeom");
    m_pAxisGeom->SetMaterials(pMats);
    m_pAxisGeom->SetEnabled(false);

    vtMesh *pMesh = new vtMesh(osg::PrimitiveSet::LINES, 0, 6);
    pMesh->AddVertex(FPoint3(0,2,0));
    pMesh->AddVertex(FPoint3(0,-2,0));
    pMesh->AddLine(0,1);
    m_pAxisGeom->AddMesh(pMesh, green);
    m_top->addChild(m_pAxisGeom);

#if 0
    axis = WireAxis(RGBf(1,1,1), 1.1f);
    m_top->addChild(axis);
#endif
}
Beispiel #24
0
void vtFence3d::ShowBounds(bool bShow)
{
	if (m_pHighlightMesh)
	{
		// remove previous
		m_pFenceGeom->RemoveMesh(m_pHighlightMesh);
		m_pHighlightMesh = NULL;
	}
	if (bShow)
	{
		uint i, npoints = m_pFencePts.GetSize();

		// Create border around the feature, also some lines as handles for
		//  the control points.
		// Must be tall enough to be visible above all the posts and profile.
		float height = max(m_Params.m_fPostHeight, m_Params.m_fConnectTop);
		float width = m_Params.m_fConnectWidth;
		if (m_Params.m_iConnectType == 3)
		{
			for (i = 0; i < m_Profile.GetSize(); i++)
			{
				float x = fabs(m_Profile[i].x), y = m_Profile[i].y;
				if (y > height) height = y;
				if (x > width) width = x;
			}
		}
		height += 1.0f;
		width += 1.0f;

		// border around the feature
		m_pHighlightMesh = new vtMesh(osg::PrimitiveSet::LINE_STRIP, 0, npoints*2);
		FPoint3 sideways, up(0,1,0);
		for (i = 0; i < npoints; i++)
		{
			// determine normal
			if (i == 0)
				sideways = SidewaysVector(m_Posts3d[i], m_Posts3d[i+1]);
			else if (i > 0 && i < npoints-1)
			{
				AngleSideVector(m_Posts3d[i-1], m_Posts3d[i], m_Posts3d[i+1], sideways);
				sideways = -sideways;	// We want a vector pointing left, not right
			}
			else if (i == npoints-1)
				sideways = SidewaysVector(m_Posts3d[i-1], m_Posts3d[i]);

			sideways.SetLength(width);

			m_pHighlightMesh->AddVertex(m_Posts3d[i] - sideways + up);
			m_pHighlightMesh->AddVertex(m_Posts3d[i] + sideways + up);
		}

		std::vector<unsigned short> idx;
		for (i = 0; i < npoints; i++) idx.push_back(i*2);
		for (i = 0; i < npoints; i++) idx.push_back((npoints*2)-1 - i*2);
		idx.push_back(0);
		m_pHighlightMesh->AddStrip(idx.size(), &idx.front());

		for (i = 0; i < npoints; i++)
		{
			float extra_height = 0.0f;
			if (m_Params.m_bConstantTop)
				extra_height = m_fMaxGroundY - m_Posts3d[i].y;

			int v0 = m_pHighlightMesh->AddVertex(m_Posts3d[i]);
			int v1 = m_pHighlightMesh->AddVertex(m_Posts3d[i] + FPoint3(0,height+extra_height,0));
			m_pHighlightMesh->AddLine(v0, v1);
		}

		// Use yellow highlight material
		int highlight_matidx = GetMatIndex("Highlight", RGBf(1,1,0));

		m_pFenceGeom->AddMesh(m_pHighlightMesh, highlight_matidx);
	}
}