void vtIcoGlobe::CreateCoreMaterials() { m_coremats = new vtMaterialArray; m_red = m_coremats->AddRGBMaterial1(RGBf(1.0f, 0.0f, 0.0f), // red false, false, true); m_yellow = m_coremats->AddRGBMaterial1(RGBf(1.0f, 1.0f, 0.0f), // yellow false, false, false); m_white = m_coremats->AddRGBMaterial1(RGBf(0.2f, 0.2f, 0.2f), true, true, true, 1); m_coremats->at(m_white)->SetTransparent(true, true); }
void vtRoute::_CreateMaterials() { m_pRouteMats = new vtMaterialArray; // add wire material (0) m_mi_wire = m_pRouteMats->AddRGBMaterial(RGBf(0.0f, 0.0f, 0.0f), // diffuse // RGBf(0.5f, 0.5f, 0.5f), // ambient grey RGBf(1.5f, 1.5f, 1.5f), // ambient bright white false, true, false, // culling, lighting, wireframe 1.0f); // alpha }
void Style::CreateDefaultStyle(hStyle h) { bool isDefaultStyle = true; const Default *d; for(d = &(Defaults[0]); d->h.v; d++) { if(d->h.v == h.v) break; } if(!d->h.v) { // Not a default style; so just create it the same as our default // active group entity style. d = &(Defaults[0]); isDefaultStyle = false; } Style ns; ZERO(&ns); ns.color = CnfThawColor(d->color, CnfColor(d->cnfPrefix)); ns.width = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix)); ns.widthAs = UNITS_AS_PIXELS; ns.textHeight = DEFAULT_TEXT_HEIGHT; ns.textHeightAs = UNITS_AS_PIXELS; ns.textOrigin = 0; ns.textAngle = 0; ns.visible = true; ns.exportable = true; ns.filled = false; ns.fillColor = RGBf(0.3, 0.3, 0.3); ns.h = h; if(isDefaultStyle) { ns.name.strcpy(CnfPrefixToName(d->cnfPrefix)); } else { ns.name.strcpy("new-custom-style"); } SK.style.Add(&ns); }
ElasticPolyline::ElasticPolyline() { m_Materials = new vtMaterialArray; m_Materials->AddRGBMaterial1(RGBf(1, 0.5, 0), true, true); // orange solid m_Materials->AddRGBMaterial1(RGBf(1, 1, 0.5), false, false, true); // light yellow wireframe // Create a marker post to use for each corner of the polyline int matidx = 0; // orange float fRadius = 0.1f; m_Marker = CreateCylinderGeom(m_Materials, matidx, VT_Normals, 1.0f, fRadius, 10, true, false, false, 1); m_Container = new vtGroup; m_pTerr = NULL; // Defaults m_fPostHeight = 1.0f; m_fLineHeight = 1.0f; }
void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) { if(d == NULL) d = &Defaults[0]; s->color = (factory) ? d->color : CnfThawColor(d->color, CnfColor(d->cnfPrefix)); s->width = (factory) ? d->width : CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix)); s->widthAs = UnitsAs::PIXELS; s->textHeight = (factory) ? DEFAULT_TEXT_HEIGHT : CnfThawFloat(DEFAULT_TEXT_HEIGHT, CnfTextHeight(d->cnfPrefix)); s->textHeightAs = UnitsAs::PIXELS; s->textOrigin = TextOrigin::NONE; s->textAngle = 0; s->visible = true; s->exportable = true; s->filled = false; s->fillColor = RGBf(0.3, 0.3, 0.3); s->stippleType = (d->h.v == Style::HIDDEN_EDGE) ? StipplePattern::DASH : StipplePattern::CONTINUOUS; s->stippleScale = 15.0; s->zIndex = d->zIndex; }
void Style::LoadFactoryDefaults(void) { const Default *d; for(d = &(Defaults[0]); d->h.v; d++) { Style *s = Get(d->h); s->color = d->color; s->width = d->width; s->widthAs = UNITS_AS_PIXELS; s->textHeight = DEFAULT_TEXT_HEIGHT; s->textHeightAs = UNITS_AS_PIXELS; s->textOrigin = 0; s->textAngle = 0; s->visible = true; s->exportable = true; s->filled = false; s->fillColor = RGBf(0.3, 0.3, 0.3); s->name.strcpy(CnfPrefixToName(d->cnfPrefix)); } SS.backgroundColor = RGBi(0, 0, 0); if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile); SS.bgImage.fromFile = NULL; }
/** * Get the emissive color of this material. */ RGBf vtMaterial::GetEmission() const { osg::Vec4 col = m_pMaterial->getEmission(FAB); return RGBf(col[0], col[1], col[2]); }
// // Test code // void EnviroFrame::DoTestCode() { SetMode(MM_SLOPE); #if 0 // Shadow tests const int ReceivesShadowTraversalMask = 0x1; const int CastsShadowTraversalMask = 0x2; osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene; shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask); shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask); #if 0 osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap; shadowedScene->setShadowTechnique(sm.get()); int mapres = 1024; sm->setTextureSize(osg::Vec2s(mapres,mapres)); #else osg::ref_ptr<osgShadow::ShadowTexture> sm = new osgShadow::ShadowTexture; shadowedScene->setShadowTechnique(sm.get()); #endif osg::Group* cessna1 = (osg::Group*) osgDB::readNodeFile("cessna.osg"); if (!cessna1) return; cessna1->setNodeMask(CastsShadowTraversalMask); cessna1->getChild(0)->setNodeMask(CastsShadowTraversalMask); osg::Group* cessna2 = (osg::Group*) osgDB::readNodeFile("cessna.osg"); if (!cessna2) return; int flags_off = ~(CastsShadowTraversalMask | ReceivesShadowTraversalMask); cessna2->setNodeMask(flags_off); cessna2->getChild(0)->setNodeMask(flags_off); osg::MatrixTransform* positioned = new osg::MatrixTransform; positioned->setDataVariance(osg::Object::STATIC); positioned->setMatrix(osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,1.0f,0.0f) *osg::Matrix::translate(40,40,0)); positioned->addChild(cessna1); //osg::ref_ptr<osg::Group> shadowedScene = new osg::Group; shadowedScene->addChild(positioned); shadowedScene->addChild(cessna2); // osg::ref_ptr<osg::Group> container = new osg::Group; // container->addChild(positioned); // container->addChild(cessna2); vtGroup *vtg = GetCurrentTerrain()->GetTerrainGroup(); vtg->GetOsgGroup()->addChild(shadowedScene.get()); // vtg->GetOsgGroup()->addChild(container.get()); vtLogGraph(shadowedScene.get()); #endif #if 0 if (pTerr && g_App.m_bSelectedStruct) { vtStructureArray3d *sa = pTerr->GetStructureLayer(); int i = 0; while (!sa->GetAt(i)->IsSelected()) i++; vtBuilding3d *bld = sa->GetBuilding(i); // (Do something to the building as a test) sa->ConstructStructure(bld); } #endif #if 0 { // Read points from a text file, create OBJ file with geometry at that locations FILE *fp = fopen("test.txt", "r"); if (!fp) return; char buf[80]; float depth, x, y; // Add the geometry and materials to the shape vtGeode *pGeode = new vtGeode; vtMaterialArray *pMats = new vtMaterialArray; pMats->AddRGBMaterial(RGBf(1.0f, 1.0f, 1.0f), false, false, false); pGeode->SetMaterials(pMats); vtMesh *mesh = new vtMesh(osg::PrimitiveSet::TRIANGLES, VT_Normals | VT_Colors, 4000); int line = 0; fgets(buf, 80, fp); // skip first while (fgets(buf, 80, fp) != NULL) { sscanf(buf, "%f\t%f\t%f", &depth, &x, &y); int idx = mesh->NumVertices(); for (int i = 0; i < 20; i++) { double angle = (double)i / 20.0 * PI2d; FPoint3 vec; vec.x = x/2 * cos(angle); vec.y = 0.0f; vec.z = y/2 * sin(angle); // normal FPoint3 norm = vec; norm.Normalize(); // color RGBAf col(1.0f, 1.0f, 1.0f, 1.0f); if (x > y) { float frac = (x-y)/1.5f; // typical: 0 - 1.2 col.g -= frac; col.b -= frac; } else if (y > x) { float frac = (y-x)/1.5f; // typical: 0 - 1.2 col.r -= frac; col.g -= frac; } int add = mesh->AddVertexN(vec.x, /*650*/-depth, vec.z, norm.x, norm.y, norm.z); mesh->SetVtxColor(add, col); } if (line != 0) { for (int i = 0; i < 20; i++) { int next = (i+1)%20; mesh->AddTri(idx-20 + i, idx + i, idx-20 + next); mesh->AddTri(idx + i, idx + next, idx-20 + next); } } line++; } pGeode->AddMesh(mesh, 0); WriteGeomToOBJ(pGeode, "bore.obj"); vtTransform *model = new vtTransform; model->addChild(pGeode); DPoint3 pos; g_App.m_pTerrainPicker->GetCurrentEarthPos(pos); GetCurrentTerrain()->AddNode(model); GetCurrentTerrain()->PlantModelAtPoint(model, DPoint2(pos.x, pos.y)); } #endif }
void Constraint::DrawOrGetDistance(Vector *labelPos) { if(!SS.GW.showConstraints) return; Group *g = SK.GetGroup(group); // If the group is hidden, then the constraints are hidden and not // able to be selected. if(!(g->visible)) return; // And likewise if the group is not the active group; except for comments // with an assigned style. if(g->h.v != SS.GW.activeGroup.v && !(type == COMMENT && disp.style.v)) { return; } if(disp.style.v) { Style *s = Style::Get(disp.style); if(!s->visible) return; } // Unit vectors that describe our current view of the scene. One pixel // long, not one actual unit. Vector gr = SS.GW.projRight.ScaledBy(1/SS.GW.scale); Vector gu = SS.GW.projUp.ScaledBy(1/SS.GW.scale); Vector gn = (gr.Cross(gu)).WithMagnitude(1/SS.GW.scale); switch(type) { case PT_PT_DISTANCE: { Vector ap = SK.GetEntity(ptA)->PointGetNum(); Vector bp = SK.GetEntity(ptB)->PointGetNum(); if(workplane.v != Entity::FREE_IN_3D.v) { DoProjectedPoint(&ap); DoProjectedPoint(&bp); } Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset); DoLineWithArrows(ref, ap, bp, false); DoLabel(ref, labelPos, gr, gu); break; } case PROJ_PT_DISTANCE: { Vector ap = SK.GetEntity(ptA)->PointGetNum(), bp = SK.GetEntity(ptB)->PointGetNum(), dp = (bp.Minus(ap)), pp = SK.GetEntity(entityA)->VectorGetNum(); Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset); pp = pp.WithMagnitude(1); double d = dp.Dot(pp); Vector bpp = ap.Plus(pp.ScaledBy(d)); StippledLine(ap, bpp); StippledLine(bp, bpp); DoLineWithArrows(ref, ap, bpp, false); DoLabel(ref, labelPos, gr, gu); break; } case PT_FACE_DISTANCE: case PT_PLANE_DISTANCE: { Vector pt = SK.GetEntity(ptA)->PointGetNum(); Entity *enta = SK.GetEntity(entityA); Vector n, p; if(type == PT_PLANE_DISTANCE) { n = enta->Normal()->NormalN(); p = enta->WorkplaneGetOffset(); } else { n = enta->FaceGetNormalNum(); p = enta->FaceGetPointNum(); } double d = (p.Minus(pt)).Dot(n); Vector closest = pt.Plus(n.WithMagnitude(d)); Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset); if(!pt.Equals(closest)) { DoLineWithArrows(ref, pt, closest, true); } DoLabel(ref, labelPos, gr, gu); break; } case PT_LINE_DISTANCE: { Vector pt = SK.GetEntity(ptA)->PointGetNum(); Entity *line = SK.GetEntity(entityA); Vector lA = SK.GetEntity(line->point[0])->PointGetNum(); Vector lB = SK.GetEntity(line->point[1])->PointGetNum(); Vector dl = lB.Minus(lA); if(workplane.v != Entity::FREE_IN_3D.v) { lA = lA.ProjectInto(workplane); lB = lB.ProjectInto(workplane); DoProjectedPoint(&pt); } // Find the closest point on the line Vector closest = pt.ClosestPointOnLine(lA, dl); Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset); DoLabel(ref, labelPos, gr, gu); if(!pt.Equals(closest)) { DoLineWithArrows(ref, pt, closest, true); } if(workplane.v != Entity::FREE_IN_3D.v) { // Draw the projection marker from the closest point on the // projected line to the projected point on the real line. Vector lAB = (lA.Minus(lB)); double t = (lA.Minus(closest)).DivPivoting(lAB); Vector lA = SK.GetEntity(line->point[0])->PointGetNum(); Vector lB = SK.GetEntity(line->point[1])->PointGetNum(); Vector c2 = (lA.ScaledBy(1-t)).Plus(lB.ScaledBy(t)); DoProjectedPoint(&c2); } break; } case DIAMETER: { Entity *circle = SK.GetEntity(entityA); Vector center = SK.GetEntity(circle->point[0])->PointGetNum(); Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum(); Vector n = q.RotationN().WithMagnitude(1); double r = circle->CircleGetRadiusNum(); Vector ref = center.Plus(disp.offset); // Force the label into the same plane as the circle. ref = ref.Minus(n.ScaledBy(n.Dot(ref) - n.Dot(center))); Vector mark = ref.Minus(center); mark = mark.WithMagnitude(mark.Magnitude()-r); DoLineTrimmedAgainstBox(ref, ref, ref.Minus(mark)); Vector topLeft; DoLabel(ref, &topLeft, gr, gu); if(labelPos) *labelPos = topLeft; // Show this as diameter or radius? if(!other) { // Draw the diameter symbol Vector dc = topLeft; dc = dc.Plus(gu.WithMagnitude(5/SS.GW.scale)); dc = dc.Plus(gr.WithMagnitude(9/SS.GW.scale)); double dr = 5/SS.GW.scale; double theta, dtheta = (2*PI)/12; for(theta = 0; theta < 2*PI-0.01; theta += dtheta) { LineDrawOrGetDistance( dc.Plus(gu.WithMagnitude(cos(theta)*dr)).Plus( gr.WithMagnitude(sin(theta)*dr)), dc.Plus(gu.WithMagnitude(cos(theta+dtheta)*dr)).Plus( gr.WithMagnitude(sin(theta+dtheta)*dr))); } theta = 25*(PI/180); dr *= 1.7; dtheta = PI; LineDrawOrGetDistance( dc.Plus(gu.WithMagnitude(cos(theta)*dr)).Plus( gr.WithMagnitude(sin(theta)*dr)), dc.Plus(gu.WithMagnitude(cos(theta+dtheta)*dr)).Plus( gr.WithMagnitude(sin(theta+dtheta)*dr))); } break; } case POINTS_COINCIDENT: { if(!dogd.drawing) { for(int i = 0; i < 2; i++) { Vector p = SK.GetEntity(i == 0 ? ptA : ptB)-> PointGetNum(); Point2d pp = SS.GW.ProjectPoint(p); // The point is selected within a radius of 7, from the // same center; so if the point is visible, then this // constraint cannot be selected. But that's okay. dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 3); dogd.refp = p; } break; } if(dogd.drawing) { // Let's adjust the color of this constraint to have the same // rough luma as the point color, so that the constraint does not // stand out in an ugly way. RgbaColor cd = Style::Color(Style::DATUM), cc = Style::Color(Style::CONSTRAINT); // convert from 8-bit color to a vector Vector vd = Vector::From(cd.redF(), cd.greenF(), cd.blueF()), vc = Vector::From(cc.redF(), cc.greenF(), cc.blueF()); // and scale the constraint color to have the same magnitude as // the datum color, maybe a bit dimmer vc = vc.WithMagnitude(vd.Magnitude()*0.9); // and set the color to that. ssglColorRGB(RGBf(vc.x, vc.y, vc.z)); for(int a = 0; a < 2; a++) { Vector r = SS.GW.projRight.ScaledBy((a+1)/SS.GW.scale); Vector d = SS.GW.projUp.ScaledBy((2-a)/SS.GW.scale); for(int i = 0; i < 2; i++) { Vector p = SK.GetEntity(i == 0 ? ptA : ptB)-> PointGetNum(); glBegin(GL_QUADS); ssglVertex3v(p.Plus (r).Plus (d)); ssglVertex3v(p.Plus (r).Minus(d)); ssglVertex3v(p.Minus(r).Minus(d)); ssglVertex3v(p.Minus(r).Plus (d)); glEnd(); } } } break; } case PT_ON_CIRCLE: case PT_ON_LINE: case PT_ON_FACE: case PT_IN_PLANE: { double s = 8/SS.GW.scale; Vector p = SK.GetEntity(ptA)->PointGetNum(); Vector r, d; if(type == PT_ON_FACE) { Vector n = SK.GetEntity(entityA)->FaceGetNormalNum(); r = n.Normal(0); d = n.Normal(1); } else if(type == PT_IN_PLANE) { EntityBase *n = SK.GetEntity(entityA)->Normal(); r = n->NormalU(); d = n->NormalV(); } else { r = gr; d = gu; s *= (6.0/8); // draw these a little smaller } r = r.WithMagnitude(s); d = d.WithMagnitude(s); LineDrawOrGetDistance(p.Plus (r).Plus (d), p.Plus (r).Minus(d)); LineDrawOrGetDistance(p.Plus (r).Minus(d), p.Minus(r).Minus(d)); LineDrawOrGetDistance(p.Minus(r).Minus(d), p.Minus(r).Plus (d)); LineDrawOrGetDistance(p.Minus(r).Plus (d), p.Plus (r).Plus (d)); break; } case WHERE_DRAGGED: { Vector p = SK.GetEntity(ptA)->PointGetNum(), u = p.Plus(gu.WithMagnitude(8/SS.GW.scale)).Plus( gr.WithMagnitude(8/SS.GW.scale)), uu = u.Minus(gu.WithMagnitude(5/SS.GW.scale)), ur = u.Minus(gr.WithMagnitude(5/SS.GW.scale)); // Draw four little crop marks, uniformly spaced (by ninety // degree rotations) around the point. int i; for(i = 0; i < 4; i++) { LineDrawOrGetDistance(u, uu); LineDrawOrGetDistance(u, ur); u = u.RotatedAbout(p, gn, PI/2); ur = ur.RotatedAbout(p, gn, PI/2); uu = uu.RotatedAbout(p, gn, PI/2); } break; } case SAME_ORIENTATION: { for(int i = 0; i < 2; i++) { Entity *e = SK.GetEntity(i == 0 ? entityA : entityB); Quaternion q = e->NormalGetNum(); Vector n = q.RotationN().WithMagnitude(25/SS.GW.scale); Vector u = q.RotationU().WithMagnitude(6/SS.GW.scale); Vector p = SK.GetEntity(e->point[0])->PointGetNum(); p = p.Plus(n.WithMagnitude(10/SS.GW.scale)); LineDrawOrGetDistance(p.Plus(u), p.Minus(u).Plus(n)); LineDrawOrGetDistance(p.Minus(u), p.Plus(u).Plus(n)); } break; } case EQUAL_ANGLE: { Vector ref; Entity *a = SK.GetEntity(entityA); Entity *b = SK.GetEntity(entityB); Entity *c = SK.GetEntity(entityC); Entity *d = SK.GetEntity(entityD); Vector a0 = a->VectorGetRefPoint(); Vector b0 = b->VectorGetRefPoint(); Vector c0 = c->VectorGetRefPoint(); Vector d0 = d->VectorGetRefPoint(); Vector da = a->VectorGetNum(); Vector db = b->VectorGetNum(); Vector dc = c->VectorGetNum(); Vector dd = d->VectorGetNum(); if(other) da = da.ScaledBy(-1); DoArcForAngle(a0, da, b0, db, da.WithMagnitude(40/SS.GW.scale), &ref); DoArcForAngle(c0, dc, d0, dd, dc.WithMagnitude(40/SS.GW.scale), &ref); break; } case ANGLE: { Entity *a = SK.GetEntity(entityA); Entity *b = SK.GetEntity(entityB); Vector a0 = a->VectorGetRefPoint(); Vector b0 = b->VectorGetRefPoint(); Vector da = a->VectorGetNum(); Vector db = b->VectorGetNum(); if(other) da = da.ScaledBy(-1); Vector ref; DoArcForAngle(a0, da, b0, db, disp.offset, &ref); DoLabel(ref, labelPos, gr, gu); break; } case PERPENDICULAR: { Vector u = Vector::From(0, 0, 0), v = Vector::From(0, 0, 0); Vector rn, ru; if(workplane.v == Entity::FREE_IN_3D.v) { rn = gn; ru = gu; } else { EntityBase *normal = SK.GetEntity(workplane)->Normal(); rn = normal->NormalN(); ru = normal->NormalV(); // ru meaning r_up, not u/v } for(int i = 0; i < 2; i++) { Entity *e = SK.GetEntity(i == 0 ? entityA : entityB); if(i == 0) { // Calculate orientation of perpendicular sign only // once, so that it's the same both times it's drawn u = e->VectorGetNum(); u = u.WithMagnitude(16/SS.GW.scale); v = (rn.Cross(u)).WithMagnitude(16/SS.GW.scale); // a bit of bias to stop it from flickering between the // two possibilities if(fabs(u.Dot(ru)) < fabs(v.Dot(ru)) + LENGTH_EPS) { SWAP(Vector, u, v); } if(u.Dot(ru) < 0) u = u.ScaledBy(-1); } Vector p = e->VectorGetRefPoint(); Vector s = p.Plus(u).Plus(v); LineDrawOrGetDistance(s, s.Plus(v)); Vector m = s.Plus(v.ScaledBy(0.5)); LineDrawOrGetDistance(m, m.Plus(u)); } break; } case CURVE_CURVE_TANGENT: case CUBIC_LINE_TANGENT: case ARC_LINE_TANGENT: { Vector textAt, u, v; if(type == ARC_LINE_TANGENT) { Entity *arc = SK.GetEntity(entityA); Entity *norm = SK.GetEntity(arc->normal); Vector c = SK.GetEntity(arc->point[0])->PointGetNum(); Vector p = SK.GetEntity(arc->point[other ? 2 : 1])->PointGetNum(); Vector r = p.Minus(c); textAt = p.Plus(r.WithMagnitude(14/SS.GW.scale)); u = norm->NormalU(); v = norm->NormalV(); } else if(type == CUBIC_LINE_TANGENT) { Vector n; if(workplane.v == Entity::FREE_IN_3D.v) { u = gr; v = gu; n = gn; } else { EntityBase *wn = SK.GetEntity(workplane)->Normal(); u = wn->NormalU(); v = wn->NormalV(); n = wn->NormalN(); } Entity *cubic = SK.GetEntity(entityA); Vector p = other ? cubic->CubicGetFinishNum() : cubic->CubicGetStartNum(); Vector dir = SK.GetEntity(entityB)->VectorGetNum(); Vector out = n.Cross(dir); textAt = p.Plus(out.WithMagnitude(14/SS.GW.scale)); } else { Vector n, dir; EntityBase *wn = SK.GetEntity(workplane)->Normal(); u = wn->NormalU(); v = wn->NormalV(); n = wn->NormalN(); EntityBase *eA = SK.GetEntity(entityA); // Big pain; we have to get a vector tangent to the curve // at the shared point, which could be from either a cubic // or an arc. if(other) { textAt = eA->EndpointFinish(); if(eA->type == Entity::CUBIC) { dir = eA->CubicGetFinishTangentNum(); } else { dir = SK.GetEntity(eA->point[0])->PointGetNum().Minus( SK.GetEntity(eA->point[2])->PointGetNum()); dir = n.Cross(dir); } } else { textAt = eA->EndpointStart(); if(eA->type == Entity::CUBIC) { dir = eA->CubicGetStartTangentNum(); } else { dir = SK.GetEntity(eA->point[0])->PointGetNum().Minus( SK.GetEntity(eA->point[1])->PointGetNum()); dir = n.Cross(dir); } } dir = n.Cross(dir); textAt = textAt.Plus(dir.WithMagnitude(14/SS.GW.scale)); } if(dogd.drawing) { ssglWriteTextRefCenter("T", DEFAULT_TEXT_HEIGHT, textAt, u, v, LineCallback, this); } else { dogd.refp = textAt; Point2d ref = SS.GW.ProjectPoint(dogd.refp); dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10); } break; } case PARALLEL: { for(int i = 0; i < 2; i++) { Entity *e = SK.GetEntity(i == 0 ? entityA : entityB); Vector n = e->VectorGetNum(); n = n.WithMagnitude(25/SS.GW.scale); Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale); Vector p = e->VectorGetRefPoint(); LineDrawOrGetDistance(p.Plus(u), p.Plus(u).Plus(n)); LineDrawOrGetDistance(p.Minus(u), p.Minus(u).Plus(n)); } break; } case EQUAL_RADIUS: { for(int i = 0; i < 2; i++) { DoEqualRadiusTicks(i == 0 ? entityA : entityB); } break; } case EQUAL_LINE_ARC_LEN: { Entity *line = SK.GetEntity(entityA); DoEqualLenTicks( SK.GetEntity(line->point[0])->PointGetNum(), SK.GetEntity(line->point[1])->PointGetNum(), gn); DoEqualRadiusTicks(entityB); break; } case LENGTH_RATIO: case EQUAL_LENGTH_LINES: { Vector a, b = Vector::From(0, 0, 0); for(int i = 0; i < 2; i++) { Entity *e = SK.GetEntity(i == 0 ? entityA : entityB); a = SK.GetEntity(e->point[0])->PointGetNum(); b = SK.GetEntity(e->point[1])->PointGetNum(); if(workplane.v != Entity::FREE_IN_3D.v) { DoProjectedPoint(&a); DoProjectedPoint(&b); } DoEqualLenTicks(a, b, gn); } if(type == LENGTH_RATIO) { Vector ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset); DoLabel(ref, labelPos, gr, gu); } break; } case EQ_LEN_PT_LINE_D: { Entity *forLen = SK.GetEntity(entityA); Vector a = SK.GetEntity(forLen->point[0])->PointGetNum(), b = SK.GetEntity(forLen->point[1])->PointGetNum(); if(workplane.v != Entity::FREE_IN_3D.v) { DoProjectedPoint(&a); DoProjectedPoint(&b); } DoEqualLenTicks(a, b, gn); Entity *ln = SK.GetEntity(entityB); Vector la = SK.GetEntity(ln->point[0])->PointGetNum(), lb = SK.GetEntity(ln->point[1])->PointGetNum(); Vector pt = SK.GetEntity(ptA)->PointGetNum(); if(workplane.v != Entity::FREE_IN_3D.v) { DoProjectedPoint(&pt); la = la.ProjectInto(workplane); lb = lb.ProjectInto(workplane); } Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la)); LineDrawOrGetDistance(pt, closest); DoEqualLenTicks(pt, closest, gn); break; } case EQ_PT_LN_DISTANCES: { for(int i = 0; i < 2; i++) { Entity *ln = SK.GetEntity(i == 0 ? entityA : entityB); Vector la = SK.GetEntity(ln->point[0])->PointGetNum(), lb = SK.GetEntity(ln->point[1])->PointGetNum(); Entity *pte = SK.GetEntity(i == 0 ? ptA : ptB); Vector pt = pte->PointGetNum(); if(workplane.v != Entity::FREE_IN_3D.v) { DoProjectedPoint(&pt); la = la.ProjectInto(workplane); lb = lb.ProjectInto(workplane); } Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la)); LineDrawOrGetDistance(pt, closest); DoEqualLenTicks(pt, closest, gn); } break; } { case SYMMETRIC: Vector n; n = SK.GetEntity(entityA)->Normal()->NormalN(); goto s; case SYMMETRIC_HORIZ: n = SK.GetEntity(workplane)->Normal()->NormalU(); goto s; case SYMMETRIC_VERT: n = SK.GetEntity(workplane)->Normal()->NormalV(); goto s; case SYMMETRIC_LINE: { Entity *ln = SK.GetEntity(entityA); Vector la = SK.GetEntity(ln->point[0])->PointGetNum(), lb = SK.GetEntity(ln->point[1])->PointGetNum(); la = la.ProjectInto(workplane); lb = lb.ProjectInto(workplane); n = lb.Minus(la); Vector nw = SK.GetEntity(workplane)->Normal()->NormalN(); n = n.RotatedAbout(nw, PI/2); goto s; } s: Vector a = SK.GetEntity(ptA)->PointGetNum(); Vector b = SK.GetEntity(ptB)->PointGetNum(); for(int i = 0; i < 2; i++) { Vector tail = (i == 0) ? a : b; Vector d = (i == 0) ? b : a; d = d.Minus(tail); // Project the direction in which the arrow is drawn normal // to the symmetry plane; for projected symmetry constraints, // they might not be in the same direction, even when the // constraint is fully solved. d = n.ScaledBy(d.Dot(n)); d = d.WithMagnitude(20/SS.GW.scale); Vector tip = tail.Plus(d); LineDrawOrGetDistance(tail, tip); d = d.WithMagnitude(9/SS.GW.scale); LineDrawOrGetDistance(tip, tip.Minus(d.RotatedAbout(gn, 0.6))); LineDrawOrGetDistance(tip, tip.Minus(d.RotatedAbout(gn, -0.6))); } break; } case AT_MIDPOINT: case HORIZONTAL: case VERTICAL: if(entityA.v) { Vector r, u, n; if(workplane.v == Entity::FREE_IN_3D.v) { r = gr; u = gu; n = gn; } else { r = SK.GetEntity(workplane)->Normal()->NormalU(); u = SK.GetEntity(workplane)->Normal()->NormalV(); n = r.Cross(u); } // For "at midpoint", this branch is always taken. Entity *e = SK.GetEntity(entityA); Vector a = SK.GetEntity(e->point[0])->PointGetNum(); Vector b = SK.GetEntity(e->point[1])->PointGetNum(); Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5)); Vector offset = (a.Minus(b)).Cross(n); offset = offset.WithMagnitude(13/SS.GW.scale); // Draw midpoint constraint on other side of line, so that // a line can be midpoint and horizontal at same time. if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1); if(dogd.drawing) { const char *s = (type == HORIZONTAL) ? "H" : ( (type == VERTICAL) ? "V" : ( (type == AT_MIDPOINT) ? "M" : NULL)); ssglWriteTextRefCenter(s, DEFAULT_TEXT_HEIGHT, m.Plus(offset), r, u, LineCallback, this); } else { dogd.refp = m.Plus(offset); Point2d ref = SS.GW.ProjectPoint(dogd.refp); dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10); } } else { Vector a = SK.GetEntity(ptA)->PointGetNum(); Vector b = SK.GetEntity(ptB)->PointGetNum(); Entity *w = SK.GetEntity(workplane); Vector cu = w->Normal()->NormalU(); Vector cv = w->Normal()->NormalV(); Vector cn = w->Normal()->NormalN(); int i; for(i = 0; i < 2; i++) { Vector o = (i == 0) ? a : b; Vector oo = (i == 0) ? a.Minus(b) : b.Minus(a); Vector d = (type == HORIZONTAL) ? cu : cv; if(oo.Dot(d) < 0) d = d.ScaledBy(-1); Vector dp = cn.Cross(d); d = d.WithMagnitude(14/SS.GW.scale); Vector c = o.Minus(d); LineDrawOrGetDistance(o, c); d = d.WithMagnitude(3/SS.GW.scale); dp = dp.WithMagnitude(2/SS.GW.scale); if(dogd.drawing) { glBegin(GL_QUADS); ssglVertex3v((c.Plus(d)).Plus(dp)); ssglVertex3v((c.Minus(d)).Plus(dp)); ssglVertex3v((c.Minus(d)).Minus(dp)); ssglVertex3v((c.Plus(d)).Minus(dp)); glEnd(); } else { Point2d ref = SS.GW.ProjectPoint(c); dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-6); } } } break; case COMMENT: { if(dogd.drawing && disp.style.v) { ssglLineWidth(Style::Width(disp.style)); ssglColorRGB(Style::Color(disp.style)); } Vector u, v; if(workplane.v == Entity::FREE_IN_3D.v) { u = gr; v = gu; } else { EntityBase *norm = SK.GetEntity(workplane)->Normal(); u = norm->NormalU(); v = norm->NormalV(); } DoLabel(disp.offset, labelPos, u, v); break; } default: oops(); } }
bool TextWindow::EditControlDoneForConfiguration(const char *s) { switch(edit.meaning) { case EDIT_LIGHT_INTENSITY: SS.lightIntensity[edit.i] = min(1, max(0, atof(s))); InvalidateGraphics(); break; case EDIT_LIGHT_DIRECTION: { double x, y, z; if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) { SS.lightDir[edit.i] = Vector::From(x, y, z); } else { Error("Bad format: specify coordinates as x, y, z"); } InvalidateGraphics(); break; } case EDIT_COLOR: { Vector rgb; if(sscanf(s, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) { rgb = rgb.ClampWithin(0, 1); SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z); } else { Error("Bad format: specify color as r, g, b"); } break; } case EDIT_CHORD_TOLERANCE: { SS.chordTol = min(10, max(0.1, atof(s))); SS.GenerateAll(0, INT_MAX); break; } //RT New stuff case EDIT_RENDERDETAIL: { SS.renderDetailWhenSaving = atof(s); if (SS.renderDetailWhenSaving) SS.GW.scaleWin =SS.renderDetailWhenSaving; SS.GenerateAll(0, INT_MAX); break; } //RT End stuff case EDIT_MAX_SEGMENTS: { SS.maxSegments = min(1000, max(7, atoi(s))); SS.GenerateAll(0, INT_MAX); break; } case EDIT_CAMERA_TANGENT: { SS.cameraTangent = (min(2, max(0, atof(s))))/1000.0; if(!SS.usePerspectiveProj) { Message("The perspective factor will have no effect until you " "enable View -> Use Perspective Projection."); } InvalidateGraphics(); break; } case EDIT_GRID_SPACING: { SS.gridSpacing = (float)min(1e4, max(1e-3, SS.StringToMm(s))); InvalidateGraphics(); break; } case EDIT_DIGITS_AFTER_DECIMAL: { int v = atoi(s); if(v < 0 || v > 8) { Error("Specify between 0 and 8 digits after the decimal."); } else { SS.SetUnitDigitsAfterDecimal(v); } InvalidateGraphics(); break; } case EDIT_EXPORT_SCALE: { Expr *e = Expr::From(s, true); if(e) { double ev = e->Eval(); if(fabs(ev) < 0.001 || isnan(ev)) { Error("Export scale must not be zero!"); } else { SS.exportScale = (float)ev; } } break; } case EDIT_EXPORT_OFFSET: { Expr *e = Expr::From(s, true); if(e) { double ev = SS.ExprToMm(e); if(isnan(ev) || ev < 0) { Error("Cutter radius offset must not be negative!"); } else { SS.exportOffset = (float)ev; } } break; } case EDIT_CANVAS_SIZE: { Expr *e = Expr::From(s, true); if(!e) { break; } float d = (float)SS.ExprToMm(e); switch(edit.i) { case 0: SS.exportMargin.left = d; break; case 1: SS.exportMargin.right = d; break; case 2: SS.exportMargin.bottom = d; break; case 3: SS.exportMargin.top = d; break; case 10: SS.exportCanvas.width = d; break; case 11: SS.exportCanvas.height = d; break; case 12: SS.exportCanvas.dx = d; break; case 13: SS.exportCanvas.dy = d; break; } break; } case EDIT_G_CODE_DEPTH: { Expr *e = Expr::From(s, true); if(e) SS.gCode.depth = (float)SS.ExprToMm(e); break; } case EDIT_G_CODE_PASSES: { Expr *e = Expr::From(s, true); if(e) SS.gCode.passes = (int)(e->Eval()); SS.gCode.passes = max(1, min(1000, SS.gCode.passes)); break; } case EDIT_G_CODE_FEED: { Expr *e = Expr::From(s, true); if(e) SS.gCode.feed = (float)SS.ExprToMm(e); break; } case EDIT_G_CODE_PLUNGE_FEED: { Expr *e = Expr::From(s, true); if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e); break; } default: return false; } return true; }
vtMaterialArray *vtIcoGlobe::CreateMaterialsFromFiles(const vtString &strImagePrefix) { vtMaterialArray *mats = new vtMaterialArray; #if 0 if (m_style == INDEPENDENT_GEODESIC) { int mat = 0; for (int pair = 0; pair < 10; pair++) { for (int j = 0; j < m_freq; j++) for (int i = 0; i < m_freq; i++) { // TEMP for testing: pretty colors float r = (pair+1) * (1.0f / 10); float g = (j+1) * (1.0f / m_freq); float b = (i+1) * (1.0f / m_freq); m_globe_mat[mat++] = mats->AddRGBMaterial1(RGBf(r, g, b), true, true); } } return; } #endif vtString base; vtString fname; vtString fullpath; bool bCulling = true; bool bLighting = false; int pair, index; for (pair = 0; pair < 10; pair++) { if (strImagePrefix == "") { m_globe_mat[pair] = m_white; continue; } int f1 = icosa_face_pairs[pair][0]; int f2 = icosa_face_pairs[pair][1]; base = "WholeEarth/"; base += strImagePrefix; base += "_"; fname.Format("%s%02d%02d.jpg", (const char *)base, f1+1, f2+1); VTLOG("\t texture: %s\n", (const char *)fname); fullpath = FindFileOnPaths(vtGetDataPath(), (const char *)fname); if (fullpath == "") { // try again with png fname.Format("%s%02d%02d.png", (const char *)base, f1+1, f2+1); VTLOG("\t texture: %s\n", (const char *)fname); fullpath = FindFileOnPaths(vtGetDataPath(), (const char *)fname); } if (fullpath == "") { VTLOG("\t\tnot found on data paths.\n"); index = -1; } else { ImagePtr img = osgDB::readImageFile((const char *)fullpath); if (img.valid()) { index = mats->AddTextureMaterial(img, bCulling, bLighting, GetDepth(img) == 32, false, // transp, additive 0.1f, 1.0f, 1.0f, 0.0f, // ambient, diffuse, alpha, emmisive false, true, false); // texgen, clamp, mipmap } else index = -1; } if (index == -1) { VTLOG("\t\ttexture load failed, using red material.\n"); m_globe_mat[pair] = m_red; } else m_globe_mat[pair] = index; } return mats; }
bool TextWindow::EditControlDoneForStyles(const char *str) { Style *s; switch(edit.meaning) { case EDIT_STYLE_TEXT_HEIGHT: case EDIT_STYLE_WIDTH: { SS.UndoRemember(); s = Style::Get(edit.style); double v; int units = (edit.meaning == EDIT_STYLE_TEXT_HEIGHT) ? s->textHeightAs : s->widthAs; if(units == Style::UNITS_AS_MM) { v = SS.StringToMm(str); } else { v = atof(str); } v = max(0, v); if(edit.meaning == EDIT_STYLE_TEXT_HEIGHT) { s->textHeight = v; } else { s->width = v; } break; } case EDIT_STYLE_TEXT_ANGLE: SS.UndoRemember(); s = Style::Get(edit.style); s->textAngle = WRAP_SYMMETRIC(atof(str), 360); break; case EDIT_BACKGROUND_COLOR: case EDIT_STYLE_FILL_COLOR: case EDIT_STYLE_COLOR: { Vector rgb; if(sscanf(str, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) { rgb = rgb.ClampWithin(0, 1); if(edit.meaning == EDIT_STYLE_COLOR) { SS.UndoRemember(); s = Style::Get(edit.style); s->color = RGBf(rgb.x, rgb.y, rgb.z); } else if(edit.meaning == EDIT_STYLE_FILL_COLOR) { SS.UndoRemember(); s = Style::Get(edit.style); s->fillColor = RGBf(rgb.x, rgb.y, rgb.z); } else { SS.backgroundColor = RGBf(rgb.x, rgb.y, rgb.z); } } else { Error("Bad format: specify color as r, g, b"); } break; } case EDIT_STYLE_NAME: if(!StringAllPrintable(str) || !*str) { Error("Invalid characters. Allowed are: A-Z a-z 0-9 _ -"); } else { SS.UndoRemember(); s = Style::Get(edit.style); s->name.strcpy(str); } break; case EDIT_BACKGROUND_IMG_SCALE: { Expr *e = Expr::From(str, true); if(e) { double ev = e->Eval(); if(ev < 0.001 || isnan(ev)) { Error("Scale must not be zero or negative!"); } else { SS.bgImage.scale = ev / SS.MmPerUnit(); } } break; } default: return false; } return true; }
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 }
//----------------------------------------------------------------------------- // The edit control is visible, and the user just pressed enter. //----------------------------------------------------------------------------- void TextWindow::EditControlDone(const char *s) { edit.showAgain = false; switch(edit.meaning) { case EDIT_TIMES_REPEATED: { Expr *e = Expr::From(s, true); if(e) { SS.UndoRemember(); double ev = e->Eval(); if((int)ev < 1) { Error("Can't repeat fewer than 1 time."); break; } if((int)ev > 999) { Error("Can't repeat more than 999 times."); break; } Group *g = SK.GetGroup(edit.group); g->valA = ev; if(g->type == Group::ROTATE) { int i, c = 0; for(i = 0; i < SK.constraint.n; i++) { if(SK.constraint.elem[i].group.v == g->h.v) c++; } // If the group does not contain any constraints, then // set the numerical guess to space the copies uniformly // over one rotation. Don't touch the guess if we're // already constrained, because that would break // convergence. if(c == 0) { double copies = (g->skipFirst) ? (ev + 1) : ev; SK.GetParam(g->h.param(3))->val = PI/(2*copies); } } SS.MarkGroupDirty(g->h); SS.later.generateAll = true; } break; } case EDIT_GROUP_NAME: { if(!StringAllPrintable(s) || !*s) { Error("Invalid characters. Allowed are: A-Z a-z 0-9 _ -"); } else { SS.UndoRemember(); Group *g = SK.GetGroup(edit.group); g->name.strcpy(s); } break; } case EDIT_GROUP_SCALE: { Expr *e = Expr::From(s, true); if(e) { double ev = e->Eval(); if(fabs(ev) < 1e-6) { Error("Scale cannot be zero."); } else { Group *g = SK.GetGroup(edit.group); g->scale = ev; SS.MarkGroupDirty(g->h); SS.later.generateAll = true; } } break; } case EDIT_GROUP_COLOR: { Vector rgb; if(sscanf(s, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) { rgb = rgb.ClampWithin(0, 1); Group *g = SK.group.FindByIdNoOops(SS.TW.shown.group); if(!g) break; g->color = RGBf(rgb.x, rgb.y, rgb.z); SS.MarkGroupDirty(g->h); SS.later.generateAll = true; SS.GW.ClearSuper(); } else { Error("Bad format: specify color as r, g, b"); } break; } case EDIT_TTF_TEXT: { SS.UndoRemember(); Request *r = SK.request.FindByIdNoOops(edit.request); if(r) { r->str.strcpy(s); SS.MarkGroupDirty(r->group); SS.later.generateAll = true; } break; } case EDIT_STEP_DIM_FINISH: { Expr *e = Expr::From(s, true); if(!e) { break; } if(shown.dimIsDistance) { shown.dimFinish = SS.ExprToMm(e); } else { shown.dimFinish = e->Eval(); } break; } case EDIT_STEP_DIM_STEPS: shown.dimSteps = min(300, max(1, atoi(s))); break; case EDIT_TANGENT_ARC_RADIUS: { Expr *e = Expr::From(s, true); if(!e) break; if(e->Eval() < LENGTH_EPS) { Error("Radius cannot be zero or negative."); break; } SS.tangentArcRadius = SS.ExprToMm(e); break; } default: { int cnt = 0; if(EditControlDoneForStyles(s)) cnt++; if(EditControlDoneForConfiguration(s)) cnt++; if(EditControlDoneForPaste(s)) cnt++; if(EditControlDoneForView(s)) cnt++; if(cnt > 1) { // The identifiers were somehow assigned not uniquely? oops(); } break; } } InvalidateGraphics(); SS.later.showTW = true; if(!edit.showAgain) { HideEditControl(); edit.meaning = EDIT_NOTHING; } }
/** * Get the ambient color of this material. */ RGBf vtMaterial::GetAmbient() const { osg::Vec4 col = m_pMaterial->getAmbient(FAB); return RGBf(col[0], col[1], col[2]); }
/** * Get the specular color of this material. */ RGBf vtMaterial::GetSpecular() const { osg::Vec4 col = m_pMaterial->getSpecular(FAB); return RGBf(col[0], col[1], col[2]); }
//----------------------------------------------------------------------------- // Implementation of a cosmetic line style, which determines the color and // other appearance of a line or curve on-screen and in exported files. Some // styles are predefined, and others can be created by the user. // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- #include "solvespace.h" #include <png.h> const Style::Default Style::Defaults[] = { { { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, }, { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, }, { { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, }, { { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, }, { { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.0, }, { { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, }, { { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, }, { { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, }, { { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.0, }, { { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, }, { { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 1.0, }, { { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, }, { { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, }, { { 0 }, NULL, NULL_COLOR, 0.0 } }; char *Style::CnfColor(const char *prefix) { static char name[100]; sprintf(name, "Style_%s_Color", prefix); return name;
void vtRoadMap3d::_CreateMaterials(bool do_texture) { m_pMats = new vtMaterialArray; // road textures if (do_texture) { // TODO: put these literals in a config file somewhere, if needed. m_mi_roadside = _CreateMaterial("roadside_32.png", true); m_mi_pavement = _CreateMaterial("pavement_256.jpg", false); m_mi_roads = _CreateMaterial("roadset_2k.jpg", false); m_mi_4wd = _CreateMaterial("road_4wd2.png", true); m_mi_trail = _CreateMaterial("trail2.png", true); m_mi_gravel = _CreateMaterial("gravel1.png", true); m_vt[VTI_MARGIN].m_idx = m_mi_roads; m_vt[VTI_MARGIN].m_rect.SetRect(960.0f/ROAD_REZ, 1, 992.0f/ROAD_REZ, 0); m_vt[VTI_SIDEWALK].m_idx = m_mi_roads; m_vt[VTI_SIDEWALK].m_rect.SetRect(512.0f/ROAD_REZ, 1, 640.0f/ROAD_REZ, 0); m_vt[VTI_1LANE].m_idx = m_mi_roads; m_vt[VTI_1LANE].m_rect.SetRect(451.0f/ROAD_REZ, 1, 511.0f/ROAD_REZ, 0); m_vt[VTI_2LANE1WAY].m_idx = m_mi_roads; m_vt[VTI_2LANE1WAY].m_rect.SetRect(4.0f/ROAD_REZ, 1, 124.0f/ROAD_REZ, 0); m_vt[VTI_2LANE2WAY].m_idx = m_mi_roads; m_vt[VTI_2LANE2WAY].m_rect.SetRect(640.0f/ROAD_REZ, 1, 768.0f/ROAD_REZ, 0); m_vt[VTI_3LANE1WAY].m_idx = m_mi_roads; m_vt[VTI_3LANE1WAY].m_rect.SetRect(2.0f/ROAD_REZ, 1, 190.0f/ROAD_REZ, 0); m_vt[VTI_3LANE2WAY].m_idx = m_mi_roads; m_vt[VTI_3LANE2WAY].m_rect.SetRect(768.0f/ROAD_REZ, 1, .0f/ROAD_REZ, 0); m_vt[VTI_4LANE1WAY].m_idx = m_mi_roads; m_vt[VTI_4LANE1WAY].m_rect.SetRect(0.0f/ROAD_REZ, 1, 256.0f/ROAD_REZ, 0); m_vt[VTI_4LANE2WAY].m_idx = m_mi_roads; m_vt[VTI_4LANE2WAY].m_rect.SetRect(256.0f/ROAD_REZ, 1, 512.0f/ROAD_REZ, 0); m_vt[VTI_RAIL].m_idx = m_mi_roads; m_vt[VTI_RAIL].m_rect.SetRect(992.0f/ROAD_REZ, 1, 1248.0f/ROAD_REZ, 0); m_vt[VTI_STONE].m_idx = m_mi_roads; m_vt[VTI_STONE].m_rect.SetRect(1248.0f/ROAD_REZ, 1, 1440.0f/ROAD_REZ, 0); m_vt[VTI_4WD].m_idx = m_mi_4wd; m_vt[VTI_4WD].m_rect.SetRect(0, 0, 1, 1); m_vt[VTI_TRAIL].m_idx = m_mi_trail; m_vt[VTI_TRAIL].m_rect.SetRect(0, 0, 1, 1); m_vt[VTI_GRAVEL].m_idx = m_mi_gravel; m_vt[VTI_GRAVEL].m_rect.SetRect(0, 0, 1, 1); m_vt[VTI_PAVEMENT].m_idx = m_mi_pavement; m_vt[VTI_PAVEMENT].m_rect.SetRect(0, 0, 1, 1); } else { m_mi_roadside = m_pMats->AddRGBMaterial(RGBf(0.8f, 0.6f, 0.4f), true, false); // 0 brown roadside m_mi_roads = m_pMats->AddRGBMaterial(RGBf(0.0f, 1.0f, 0.0f), true, false); // 1 green m_mi_4wd = m_pMats->AddRGBMaterial(RGBf(0.5f, 0.5f, 0.5f), true, false); // 2 grey m_mi_trail = m_pMats->AddRGBMaterial(RGBf(1.0f, 0.3f, 1.0f), true, false); // 3 light purple } m_mi_red = m_pMats->AddRGBMaterial(RGBf(1.0f, 0.0f, 0.0f), true, true, false, 0.4f); // red-translucent }
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); } }
void vtFence3d::AddFenceMeshes(vtHeightField3d *pHeightField) { // Trigger the creation of any materials we may need GetMatIndex(""); uint i, j; uint numfencepts = m_pFencePts.GetSize(); FLine3 p3; FPoint3 diff, fp; FPoint3 PostSize(m_Params.m_fPostWidth, m_Params.m_fPostHeight, m_Params.m_fPostDepth); // All culture (roads and buildings) can be draped on int iIncludeCulture = CE_ALL; // first, project the posts from earth to world m_Posts3d.SetSize(numfencepts); for (i = 0; i < numfencepts; i++) pHeightField->ConvertEarthToSurfacePoint(m_pFencePts[i], m_Posts3d[i], iIncludeCulture); // Find highest point m_fMaxGroundY = -1E8; for (i = 0; i < numfencepts; i++) if (m_Posts3d[i].y > m_fMaxGroundY) m_fMaxGroundY = m_Posts3d[i].y; if (m_Params.m_PostType != "none") { // has posts // determine where the fence posts go for (i = 0; i < numfencepts; i++) { if (i == numfencepts-1) { p3.Append(m_Posts3d[i]); continue; } // get start and end group points for this section FPoint3 wpos1 = m_Posts3d[i]; FPoint3 wpos2 = m_Posts3d[i+1]; // look at world distance (approximate meters, _not_ earth // coordinates, which might be in e.g. feet or degrees) diff = wpos2 - wpos1; float distance = sqrt(diff.x*diff.x+diff.z*diff.z); uint segments = (uint) (distance / m_Params.m_fPostSpacing); if (segments < 1) segments = 1; FPoint3 diff_per_segment = diff / (float) segments; for (j = 0; j < segments; j++) { fp = wpos1 + (diff_per_segment * (float)j); if (i > 0 && i < numfencepts-1) { // randomly offset by up to 4% of fence spacing, for "realism" fp.x += random_offset(0.04f * m_Params.m_fPostSpacing); fp.z += random_offset(0.04f * m_Params.m_fPostSpacing); } // false: true elevation, true: include culture (structures and roads) pHeightField->FindAltitudeAtPoint(fp, fp.y, false, CE_ALL); p3.Append(fp); } } // generate the posts // Look first for post materials (type 3) int iMatIdx = GetMatIndex(m_Params.m_PostType, RGBf(), 3); // If that didn't work, look for any material by that name if (iMatIdx == -1) int iMatIdx = GetMatIndex(m_Params.m_PostType); for (i = 0; i < p3.GetSize(); i++) AddFencepost(p3[i], iMatIdx); } else { // no post spacing to consider, so just use the input vertices p3.SetSize(numfencepts); for (i = 0; i < numfencepts; i++) p3[i] = m_Posts3d[i]; } if (m_Params.m_PostExtension != "none") AddPostExtensions(p3); // if not enough points, nothing connections to create if (p3.GetSize() < 2) return; if (m_Params.m_iConnectType == 0) // none { // nothing to do } else if (m_Params.m_iConnectType == 1) // wire { AddWireMeshes(p3); } if (m_Params.m_ConnectMaterial == "none") return; if (m_Params.m_iConnectType == 2) // simple { if (m_Params.m_fConnectWidth == 0.0f) AddFlatConnectionMesh(p3); else if (m_Params.m_fConnectWidth > 0.0f) AddThickConnectionMesh(p3); } else if (m_Params.m_iConnectType == 3) // profile { AddProfileConnectionMesh(p3); } }
void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *sm, Vector u, Vector v, Vector n, Vector origin, double cameraTan, VectorFileWriter *out) { double s = 1.0 / SS.exportScale; // Project into the export plane; so when we're done, z doesn't matter, // and x and y are what goes in the DXF. SEdge *e; for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) { // project into the specified csys, and apply export scale (e->a) = e->a.InPerspective(u, v, n, origin, cameraTan).ScaledBy(s); (e->b) = e->b.InPerspective(u, v, n, origin, cameraTan).ScaledBy(s); } SBezier *b; if(sbl) { for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) { *b = b->InPerspective(u, v, n, origin, cameraTan); int i; for(i = 0; i <= b->deg; i++) { b->ctrl[i] = (b->ctrl[i]).ScaledBy(s); } } } // If cutter radius compensation is requested, then perform it now if(fabs(SS.exportOffset) > LENGTH_EPS) { // assemble those edges into a polygon, and clear the edge list SPolygon sp; ZERO(&sp); sel->AssemblePolygon(&sp, NULL); sel->Clear(); SPolygon compd; ZERO(&compd); sp.normal = Vector::From(0, 0, -1); sp.FixContourDirections(); sp.OffsetInto(&compd, SS.exportOffset*s); sp.Clear(); compd.MakeEdgesInto(sel); compd.Clear(); } // Now the triangle mesh; project, then build a BSP to perform // occlusion testing and generated the shaded surfaces. SMesh smp; ZERO(&smp); if(sm) { Vector l0 = (SS.lightDir[0]).WithMagnitude(1), l1 = (SS.lightDir[1]).WithMagnitude(1); STriangle *tr; for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) { STriangle tt = *tr; tt.a = (tt.a).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s); tt.b = (tt.b).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s); tt.c = (tt.c).InPerspective(u, v, n, origin, cameraTan).ScaledBy(s); // And calculate lighting for the triangle Vector n = tt.Normal().WithMagnitude(1); double lighting = SS.ambientIntensity + max(0, (SS.lightIntensity[0])*(n.Dot(l0))) + max(0, (SS.lightIntensity[1])*(n.Dot(l1))); double r = min(1, REDf (tt.meta.color)*lighting), g = min(1, GREENf(tt.meta.color)*lighting), b = min(1, BLUEf (tt.meta.color)*lighting); tt.meta.color = RGBf(r, g, b); smp.AddTriangle(&tt); } } // Use the BSP routines to generate the split triangles in paint order. SBsp3 *bsp = SBsp3::FromMesh(&smp); SMesh sms; ZERO(&sms); bsp->GenerateInPaintOrder(&sms); // And cull the back-facing triangles STriangle *tr; sms.l.ClearTags(); for(tr = sms.l.First(); tr; tr = sms.l.NextAfter(tr)) { Vector n = tr->Normal(); if(n.z < 0) { tr->tag = 1; } } sms.l.RemoveTagged(); // And now we perform hidden line removal if requested SEdgeList hlrd; ZERO(&hlrd); if(sm && !SS.GW.showHdnLines) { SKdNode *root = SKdNode::From(&smp); // Generate the edges where a curved surface turns from front-facing // to back-facing. if(SS.GW.showEdges) { root->MakeCertainEdgesInto(sel, SKdNode::TURNING_EDGES, false, NULL, NULL); } root->ClearTags(); int cnt = 1234; SEdge *se; for(se = sel->l.First(); se; se = sel->l.NextAfter(se)) { if(se->auxA == Style::CONSTRAINT) { // Constraints should not get hidden line removed; they're // always on top. hlrd.AddEdge(se->a, se->b, se->auxA); continue; } SEdgeList out; ZERO(&out); // Split the original edge against the mesh out.AddEdge(se->a, se->b, se->auxA); root->OcclusionTestLine(*se, &out, cnt); // the occlusion test splits unnecessarily; so fix those out.MergeCollinearSegments(se->a, se->b); cnt++; // And add the results to our output SEdge *sen; for(sen = out.l.First(); sen; sen = out.l.NextAfter(sen)) { hlrd.AddEdge(sen->a, sen->b, sen->auxA); } out.Clear(); } sel = &hlrd; } // We kept the line segments and Beziers separate until now; but put them // all together, and also project everything into the xy plane, since not // all export targets ignore the z component of the points. for(e = sel->l.First(); e; e = sel->l.NextAfter(e)) { SBezier sb = SBezier::From(e->a, e->b); sb.auxA = e->auxA; sbl->l.Add(&sb); } for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) { for(int i = 0; i <= b->deg; i++) { b->ctrl[i].z = 0; } } // If possible, then we will assemble these output curves into loops. They // will then get exported as closed paths. SBezierLoopSetSet sblss; ZERO(&sblss); SBezierList leftovers; ZERO(&leftovers); SSurface srf = SSurface::FromPlane(Vector::From(0, 0, 0), Vector::From(1, 0, 0), Vector::From(0, 1, 0)); SPolygon spxyz; ZERO(&spxyz); bool allClosed; SEdge notClosedAt; sbl->l.ClearTags(); sblss.FindOuterFacesFrom(sbl, &spxyz, &srf, SS.ChordTolMm()*s, &allClosed, ¬ClosedAt, NULL, NULL, &leftovers); for(b = leftovers.l.First(); b; b = leftovers.l.NextAfter(b)) { sblss.AddOpenPath(b); } // Now write the lines and triangles to the output file out->Output(&sblss, &sms); leftovers.Clear(); spxyz.Clear(); sblss.Clear(); smp.Clear(); sms.Clear(); hlrd.Clear(); }