示例#1
0
文件: curve.cpp 项目: Drooids/pbrt-v3
bool Curve::recursiveIntersect(const Ray &ray, Float *tHit,
                               SurfaceInteraction *isect, const Point3f cp[4],
                               const Transform &rayToObject, Float u0, Float u1,
                               int depth) const {
    // Try to cull curve segment versus ray

    // Compute bounding box of curve segment, _curveBounds_
    Bounds3f curveBounds =
        Union(Bounds3f(cp[0], cp[1]), Bounds3f(cp[2], cp[3]));
    Float maxWidth = std::max(Lerp(u0, common->width[0], common->width[1]),
                              Lerp(u1, common->width[0], common->width[1]));
    curveBounds = Expand(curveBounds, 0.5 * maxWidth);

    // Compute bounding box of ray, _rayBounds_
    Float rayLength = ray.d.Length();
    Float zMax = rayLength * ray.tMax;
    Bounds3f rayBounds(Point3f(0, 0, 0), Point3f(0, 0, zMax));
    if (Overlaps(curveBounds, rayBounds) == false) return false;
    if (depth > 0) {
        // Split curve segment into sub-segments and test for intersection
        Float uMid = 0.5f * (u0 + u1);
        Point3f cpSplit[7];
        SubdivideBezier(cp, cpSplit);
        return (recursiveIntersect(ray, tHit, isect, &cpSplit[0], rayToObject,
                                   u0, uMid, depth - 1) ||
                recursiveIntersect(ray, tHit, isect, &cpSplit[3], rayToObject,
                                   uMid, u1, depth - 1));
    } else {
        // Intersect ray with curve segment

        // Test ray against segment endpoint boundaries

        // Test sample point against tangent perpendicular at curve start
        Float edge =
            (cp[1].y - cp[0].y) * -cp[0].y + cp[0].x * (cp[0].x - cp[1].x);
        if (edge < 0) return false;

        // Test sample point against tangent perpendicular at curve end
        edge = (cp[2].y - cp[3].y) * -cp[3].y + cp[3].x * (cp[3].x - cp[2].x);
        if (edge < 0) return false;

        // Compute line $w$ that gives minimum distance to sample point
        Vector2f segmentDirection = Point2f(cp[3]) - Point2f(cp[0]);
        Float denom = segmentDirection.LengthSquared();
        if (denom == 0) return false;
        Float w = Dot(-Vector2f(cp[0]), segmentDirection) / denom;

        // Compute $u$ coordinate of curve intersection point and _hitWidth_
        Float u = Clamp(Lerp(w, u0, u1), u0, u1);
        Float hitWidth = Lerp(u, common->width[0], common->width[1]);
        Normal3f nHit;
        if (common->type == CurveType::Ribbon) {
            // Scale _hitWidth_ based on ribbon orientation
            Float sin0 = std::sin((1 - u) * common->normalAngle) *
                         common->invSinNormalAngle;
            Float sin1 =
                std::sin(u * common->normalAngle) * common->invSinNormalAngle;
            nHit = sin0 * common->n[0] + sin1 * common->n[1];
            hitWidth *= AbsDot(nHit, ray.d) / rayLength;
        }

        // Test intersection point against curve width
        Vector3f dpcdw;
        Point3f pc = EvalBezier(cp, Clamp(w, 0, 1), &dpcdw);
        Float ptCurveDist2 = pc.x * pc.x + pc.y * pc.y;
        if (ptCurveDist2 > hitWidth * hitWidth * .25) return false;
        if (pc.z < 0 || pc.z > zMax) return false;

        // Compute $v$ coordinate of curve intersection point
        Float ptCurveDist = std::sqrt(ptCurveDist2);
        Float edgeFunc = dpcdw.x * -pc.y + pc.x * dpcdw.y;
        Float v = (edgeFunc > 0) ? 0.5f + ptCurveDist / hitWidth
                                 : 0.5f - ptCurveDist / hitWidth;

        // Compute hit _t_ and partial derivatives for curve intersection
        if (tHit != nullptr) {
            // FIXME: this tHit isn't quite right for ribbons...
            *tHit = pc.z / rayLength;
            // Compute error bounds for curve intersection
            Vector3f pError(2 * hitWidth, 2 * hitWidth, 2 * hitWidth);

            // Compute $\dpdu$ and $\dpdv$ for curve intersection
            Vector3f dpdu, dpdv;
            EvalBezier(common->cpObj, u, &dpdu);
            if (common->type == CurveType::Ribbon)
                dpdv = Normalize(Cross(nHit, dpdu)) * hitWidth;
            else {
                // Compute curve $\dpdv$ for flat and cylinder curves
                Vector3f dpduPlane = (Inverse(rayToObject))(dpdu);
                Vector3f dpdvPlane =
                    Normalize(Vector3f(-dpduPlane.y, dpduPlane.x, 0)) *
                    hitWidth;
                if (common->type == CurveType::Cylinder) {
                    // Rotate _dpdvPlane_ to give cylindrical appearance
                    Float theta = Lerp(v, -90., 90.);
                    Transform rot = Rotate(-theta, dpduPlane);
                    dpdvPlane = rot(dpdvPlane);
                }
                dpdv = rayToObject(dpdvPlane);
            }
            *isect = (*ObjectToWorld)(SurfaceInteraction(
                ray(pc.z), pError, Point2f(u, v), -ray.d, dpdu, dpdv,
                Normal3f(0, 0, 0), Normal3f(0, 0, 0), ray.time, this));
        }
        ++nHits;
        return true;
    }
}
示例#2
0
BOOL
TrackMouseCallBack::point_on_obj(ViewExp& vpt, IPoint2 m, Point3& pt, Point3 &norm)
{
	if ( ! vpt.IsAlive() )
	{
		// why are we here
		DbgAssert(!_T("Invalid viewport!"));
		return FALSE;
	}

	// computes the normal ray at the point of intersection
	Ray ray, world_ray;
	float at, best_dist = 0.0f;
	TimeValue t = MAXScript_time();	
	Object *obj = NULL;
	Matrix3 obtm, iobtm;
	Point3 testNorm;

	BOOL found_hit = FALSE;
	
	vl->face_num_val = vl->face_bary = &undefined;
	hit_node = NULL;

	// Calculate a ray from the mouse point
	vpt.MapScreenToWorldRay(float(m.x), float(m.y), world_ray);

	for( int i=(nodeTab.Count()-1); i>=0; i-- ) {
		// Get the object from the node
		INode* node = nodeTab[i];
		ObjectState os = node->EvalWorldState(t);
		obj = os.obj;	

		// Back transform the ray into object space.
		obtm	= node->GetObjectTM(t);
		iobtm	= Inverse(obtm);
		ray.p   = iobtm * world_ray.p;
		ray.dir = VectorTransform(iobtm, world_ray.dir);
		
		// See if we hit the object
		if (obj->IsSubClassOf(triObjectClassID))
		{
			TriObject*  tobj = (TriObject*)obj;
			DWORD		fi;
			Point3		bary;
			if (tobj->mesh.IntersectRay(ray, at, testNorm, fi, bary)  &&
			   ((!found_hit) || (at<=best_dist)) )
			{
				// Calculate the hit point and transform everything back into world space.
				// record the face index and bary coord
				best_dist = at;
				pt = ray.p + ray.dir * at;
				pt = pt * obtm;
				norm = Normalize(VectorTransform(obtm, testNorm));
				vl->face_num_val = Integer::intern(fi + 1);
				vl->face_bary = new Point3Value(bary);
				hit_node = node;
				found_hit = TRUE;
			}
		}
		else if (obj->IntersectRay(t, ray, at, testNorm)  &&
				((!found_hit) || (at<=best_dist)) )
		{
			// Calculate the hit point and transform everything back into world space.
			best_dist = at;
			pt = ray.p + ray.dir * at;
			pt = pt * obtm;
			norm = Normalize(VectorTransform(obtm, testNorm));
			hit_node = node;
			found_hit = TRUE;
		}
	}
	if( found_hit ) return TRUE;

	// Failed to find a hit on any node, look at the Normal Align Vector for the first node
	if ((obj!=NULL) && obj->NormalAlignVector(t, pt, testNorm)) // See if a default NA vector is provided
	{
		pt   = pt * obtm;
		norm = Normalize(VectorTransform(obtm, testNorm));
		return TRUE;
	}
	else
		return FALSE;
}
示例#3
0
void UnwrapMod::fnGizmoAlignToView()
{

	if (ip == NULL) return;

	ViewExp& vpt = ip->GetActiveViewExp();
	if (!vpt.IsAlive()) return;
 
	//get our tm
	//set the tm scale
	theHold.Begin();
	SuspendAnimate();
	AnimateOff();
	TimeValue t = GetCOREInterface()->GetTime();
	


	// Viewport tm
	Matrix3 vtm;
	vpt.GetAffineTM(vtm);
	vtm = Inverse(vtm);

	// Node tm
	Matrix3 ntm(1);// = nodeList[0]->GetObjectTM(ip->GetTime());

	Matrix3 destTM = vtm * Inverse(ntm);
	//get our tm
	
	
	Matrix3 initialTM = *fnGetGizmoTM();


	

	Point3 center = Normalize(initialTM.GetRow(3)); 
	initialTM.SetRow(3,center);

	for (int i = 0; i < 3; i++)
	{
		Point3 vec = destTM.GetRow(i);
		float l  = Length(initialTM.GetRow(i));
		vec = Normalize(vec) * l;
		initialTM.SetRow(i,vec);
	}



	initialTM.SetRow(3,center);


	Matrix3 ptm(1), id(1);
	initialTM = initialTM ;
	SetXFormPacket tmpck(initialTM,ptm);
	tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);

	ResumeAnimate();

	fnGizmoFit();

	if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP)  || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
		ApplyGizmo();

	theHold.Accept(GetString(IDS_MAPPING_ALIGNTOVIEW));
	fnGetGizmoTM();
	if (ip) ip->RedrawViews(ip->GetTime());

}
示例#4
0
文件: evalcol.cpp 项目: 2asoft/xray
// Returns the derivative of PObj(), relative to the pixel.
// TBD
Point3 SContext::DPObj(void)
{
	Point3 d = DP();
	return VectorTransform(Inverse(tmAfterWSM),d);
}
示例#5
0
文件: PolyOps.cpp 项目: 2asoft/xray
void FrenetFinder::ConvertPathToFrenets (Spline3D *pSpline, Matrix3 relativeTransform, Tab<Matrix3> & tFrenets,
						   int numSegs, bool align, float rotateAroundZ) {
	// Given a path, a sequence of points in 3-space, create transforms
	// for putting a cross-section around each of those points, loft-style.

	// bezShape is provided by user, tFrenets contains output, numSegs is one less than the number of transforms requested.

	// Strategy: The Z-axis is mapped along the path, and the X and Y axes 
	// are chosen in a well-defined manner to get an orthonormal basis.

	int i;

	if (numSegs < 1) return;
	tFrenets.SetCount (numSegs+1);

	int numIntervals = pSpline->Closed() ? numSegs+1 : numSegs;
	float denominator = float(numIntervals);
	Point3 xDir, yDir, zDir, location, tangent, axis;
	float position, sine, cosine, theta;
	Matrix3 rotation;

	// Find initial x,y directions:
	location = relativeTransform * pSpline->InterpCurve3D (0.0f);
	tangent = relativeTransform.VectorTransform (pSpline->TangentCurve3D (0.0f));
	zDir = tangent;

	Matrix3 inverseBasisOfSpline(1);
	if (align) {
		xDir = Point3(0.0f, 0.0f, 0.0f);
		yDir = xDir;
		mBasisFinder.BasisFromZDir (zDir, xDir, yDir);
		if (rotateAroundZ) {
			Matrix3 rotator(1);
			rotator.SetRotate (AngAxis (zDir, rotateAroundZ));
			xDir = xDir * rotator;
			yDir = yDir * rotator;
		}
		Matrix3 basisOfSpline(1);
		basisOfSpline.SetRow (0, xDir);
		basisOfSpline.SetRow (1, yDir);
		basisOfSpline.SetRow (2, tangent);
		basisOfSpline.SetTrans (location);
		inverseBasisOfSpline = Inverse (basisOfSpline);
	} else {
		inverseBasisOfSpline.SetRow (3, -location);
	}

	// Make relative transform take the spline from its own object space to our object space,
	// and from there into the space defined by its origin and initial direction:
	relativeTransform = relativeTransform * inverseBasisOfSpline;
	// (Note left-to-right evaluation order: Given matrices A,B, point x, x(AB) = (xA)B

	// The first transform is necessarily the identity:
	tFrenets[0].IdentityMatrix ();

	// Set up xDir, yDir, zDir to match our first-point basis:
	xDir = Point3 (1,0,0);
	yDir = Point3 (0,1,0);
	zDir = Point3 (0,0,1);

	for (i=1; i<=numIntervals; i++) {
		position = float(i) / denominator;
		location = relativeTransform * pSpline->InterpCurve3D (position);
		tangent = relativeTransform.VectorTransform (pSpline->TangentCurve3D (position));

		// This is the procedure we follow at each step in the path: find the
		// orthonormal basis with the right orientation, then compose with
		// the translation putting the origin at the path-point.

		// As we proceed along the path, we apply minimal rotations to
		// our original basis to keep the Z-axis tangent to the curve.
		// The X and Y axes follow in a natural manner.

		// xDir, yDir, zDir still have their values from last time...
		// Create a rotation matrix which maps the last zDir onto the current tangent:
		axis = zDir ^ tangent;	// gives axis, scaled by sine of angle.
		sine = FLength(axis);	// positive - keeps angle value in (0,PI) range.
		cosine = DotProd (zDir, tangent);	// Gives cosine of angle.
		theta = atan2f (sine, cosine);
		rotation.SetRotate (AngAxis (Normalize(axis), theta));
		Point3 testVector = rotation * zDir;
		xDir = Normalize (rotation * xDir);
		yDir = Normalize (rotation * yDir);
		zDir = tangent;

		if (i<=numSegs) {
			tFrenets[i].IdentityMatrix ();
			tFrenets[i].SetRow (0, xDir);
			tFrenets[i].SetRow (1, yDir);
			tFrenets[i].SetRow (2, tangent);
			tFrenets[i].SetTrans (location);
		}
	}
}
Matrix3 plMaxNodeBase::GetParentToWorld(TimeValue t)
{
    return Inverse(GetWorldToParent(t));
}
示例#7
0
文件: bsdfs.cpp 项目: Drooids/pbrt-v3
void TestBSDF(void (*createBSDF)(BSDF*, MemoryArena&),
              const char* description) {
    MemoryArena arena;

    Options opt;
    pbrtInit(opt);

    const int thetaRes = CHI2_THETA_RES;
    const int phiRes = CHI2_PHI_RES;
    const int sampleCount = CHI2_SAMPLECOUNT;
    Float* frequencies = new Float[thetaRes * phiRes];
    Float* expFrequencies = new Float[thetaRes * phiRes];
    RNG rng;

    int index = 0;
    std::cout.precision(3);

    // Create BSDF, which requires creating a Shape, casting a Ray that
    // hits the shape to get a SurfaceInteraction object.
    BSDF* bsdf = nullptr;
    Transform t = RotateX(-90);
    Transform tInv = Inverse(t);
    {
        bool reverseOrientation = false;
        ParamSet p;

        std::shared_ptr<Shape> disk(
            new Disk(&t, &tInv, reverseOrientation, 0., 1., 0, 360.));
        Point3f origin(0.1, 1,
                       0);  // offset slightly so we don't hit center of disk
        Vector3f direction(0, -1, 0);
        Float tHit;
        Ray r(origin, direction);
        SurfaceInteraction isect;
        disk->Intersect(r, &tHit, &isect);
        bsdf = ARENA_ALLOC(arena, BSDF)(isect);
        createBSDF(bsdf, arena);
    }

    for (int k = 0; k < CHI2_RUNS; ++k) {
        /* Randomly pick an outgoing direction on the hemisphere */
        Point2f sample {rng.UniformFloat(), rng.UniformFloat()};
        Vector3f woL = CosineSampleHemisphere(sample);
        Vector3f wo = bsdf->LocalToWorld(woL);

        FrequencyTable(bsdf, wo, rng, sampleCount, thetaRes, phiRes,
                       frequencies);

        IntegrateFrequencyTable(bsdf, wo, sampleCount, thetaRes, phiRes,
                                expFrequencies);

        std::string filename = StringPrintf("/tmp/chi2test_%s_%03i.m",
                                            description, ++index);
        DumpTables(frequencies, expFrequencies, thetaRes, phiRes,
                   filename.c_str());

        auto result =
            Chi2Test(frequencies, expFrequencies, thetaRes, phiRes, sampleCount,
                     CHI2_MINFREQ, CHI2_SLEVEL, CHI2_RUNS);
        EXPECT_TRUE(result.first) << result.second << ", iteration " << k;
    }

    delete[] frequencies;
    delete[] expFrequencies;

    pbrtCleanup();
}
示例#8
0
文件: Matrix3.cpp 项目: tocode/v5
// M^-1
Matrix3 Inverse(const Matrix3& m)
{
	Matrix3 r;
	r.mat = Inverse(m.mat);
	return r;
}
示例#9
0
void CreateRadianceProbes::Render(const Scene *scene) {
    // Compute scene bounds and initialize probe integrators
    if (bbox.pMin.x > bbox.pMax.x)
        bbox = scene->WorldBound();
    surfaceIntegrator->Preprocess(scene, camera, this);
    volumeIntegrator->Preprocess(scene, camera, this);
    Sample *origSample = new Sample(NULL, surfaceIntegrator, volumeIntegrator,
                                    scene);

    // Compute sampling rate in each dimension
    Vector delta = bbox.pMax - bbox.pMin;
    int nProbes[3];
    for (int i = 0; i < 3; ++i)
        nProbes[i] = max(1, Ceil2Int(delta[i] / probeSpacing));

    // Allocate SH coefficient vector pointers for sample points
    int count = nProbes[0] * nProbes[1] * nProbes[2];
    Spectrum **c_in = new Spectrum *[count];
    for (int i = 0; i < count; ++i)
        c_in[i] = new Spectrum[SHTerms(lmax)];

    // Compute random points on surfaces of scene

    // Create scene bounding sphere to catch rays that leave the scene
    Point sceneCenter;
    float sceneRadius;
    scene->WorldBound().BoundingSphere(&sceneCenter, &sceneRadius);
    Transform ObjectToWorld(Translate(sceneCenter - Point(0,0,0)));
    Transform WorldToObject(Inverse(ObjectToWorld));
    Reference<Shape> sph = new Sphere(&ObjectToWorld, &WorldToObject,
        true, sceneRadius, -sceneRadius, sceneRadius, 360.f);
    Reference<Material> nullMaterial = Reference<Material>(NULL);
    GeometricPrimitive sphere(sph, nullMaterial, NULL);
    vector<Point> surfacePoints;
    uint32_t nPoints = 32768, maxDepth = 32;
    surfacePoints.reserve(nPoints + maxDepth);
    Point pCamera = camera->CameraToWorld(camera->shutterOpen,
                                          Point(0, 0, 0));
    surfacePoints.push_back(pCamera);
    RNG rng;
    while (surfacePoints.size() < nPoints) {
        // Generate random path from camera and deposit surface points
        Point pray = pCamera;
        Vector dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat());
        float rayEpsilon = 0.f;
        for (uint32_t i = 0; i < maxDepth; ++i) {
            Ray ray(pray, dir, rayEpsilon, INFINITY, time);
        
            Intersection isect;
            if (!scene->Intersect(ray, &isect) &&
                !sphere.Intersect(ray, &isect))
                break;
        
            surfacePoints.push_back(ray(ray.maxt));
        
            DifferentialGeometry &hitGeometry = isect.dg;
            pray = isect.dg.p;
            rayEpsilon = isect.rayEpsilon;
            hitGeometry.nn = Faceforward(hitGeometry.nn, -ray.d);
        
            dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat());
            dir = Faceforward(dir, hitGeometry.nn);
        }
    }

    // Launch tasks to compute radiance probes at sample points
    vector<Task *> tasks;
    ProgressReporter prog(count, "Radiance Probes");
    for (int i = 0; i < count; ++i)
        tasks.push_back(new CreateRadProbeTask(i, nProbes, time,
                                   bbox, lmax, includeDirectInProbes,
                                   includeIndirectInProbes, nIndirSamples,
                                   prog, origSample, surfacePoints,
                                   scene, this, c_in[i]));
    EnqueueTasks(tasks);
    WaitForAllTasks();
    for (uint32_t i = 0; i < tasks.size(); ++i)
        delete tasks[i];
    prog.Done();

    // Write radiance probe coefficients to file
    FILE *f = fopen(filename.c_str(), "w");
    if (f) {
        if (fprintf(f, "%d %d %d\n", lmax, includeDirectInProbes?1:0, includeIndirectInProbes?1:0) < 0 ||
            fprintf(f, "%d %d %d\n", nProbes[0], nProbes[1], nProbes[2]) < 0 ||
            fprintf(f, "%f %f %f %f %f %f\n", bbox.pMin.x, bbox.pMin.y, bbox.pMin.z,
              bbox.pMax.x, bbox.pMax.y, bbox.pMax.z) < 0)
            Severe("Error writing radiance file \"%s\"", filename.c_str());
        for (int i = 0; i < nProbes[0] * nProbes[1] * nProbes[2]; ++i) {
            for (int j = 0; j < SHTerms(lmax); ++j) {
                fprintf(f, "  ");
                if (c_in[i][j].Write(f) == false)
                    Severe("Error writing radiance file \"%s\"", filename.c_str());
                fprintf(f, "\n");
            }
            fprintf(f, "\n");
        }
        fclose(f);
    }
    for (int i = 0; i < nProbes[0] * nProbes[1] * nProbes[2]; ++i)
        delete[] c_in[i];
    delete[] c_in;
    delete origSample;
}
示例#10
0
Quaternion Quaternion::Sub( const Quaternion& q ) const
{
	return Inverse()*q;
}
示例#11
0
文件: physics.cpp 项目: skopp/rush
ColMesh* RBExport::GetColMesh( INode* node )
{
    ObjectState os      = node->EvalWorldState( m_CurTime );
    Object*     pObject = os.obj;
    if (!pObject) 
    {
        Warn( "Could not evaluate object state. Collision mesh %s was skipped.", node->GetName() );
        return NULL;
    }

    Matrix3 nodeTM          = node->GetNodeTM( m_CurTime );
    Matrix3 nodeTMAfterWSM  = node->GetObjTMAfterWSM( m_CurTime );
    Matrix3 mOffs           = nodeTMAfterWSM*Inverse( nodeTM );

    //  triangulate
    TriObject* pTriObj = NULL;
    if (pObject->CanConvertToType( Class_ID( TRIOBJ_CLASS_ID, 0 ) )) 
    { 
        pTriObj = (TriObject*)pObject->ConvertToType( m_CurTime, Class_ID( TRIOBJ_CLASS_ID, 0 ) );
    }
    bool bReleaseTriObj = (pTriObj != pObject);
    if (!pTriObj) 
    {
        Warn( "Could not triangulate mesh in node. Collision mesh %s was skipped.", node->GetName() );
        return NULL;
    }

    //  ensure, that vertex winding direction in polygon is CCW
    Matrix3 objTM = node->GetObjTMAfterWSM( m_CurTime );
    bool bNegScale = (DotProd( CrossProd( objTM.GetRow(0), objTM.GetRow(1) ), objTM.GetRow(2) ) >= 0.0);

    int vx[3];
    vx[0] = bNegScale ? 2 : 0;
    vx[1] = bNegScale ? 1 : 1;
    vx[2] = bNegScale ? 0 : 2;

    Mesh& mesh = pTriObj->GetMesh();

    //  some cosmetics
    mesh.RemoveDegenerateFaces();
    mesh.RemoveIllegalFaces();
    
    //  create collision mesh
    ColMesh* pMesh = new ColMesh();
    
    int numPri  = mesh.getNumFaces();
    int numVert = mesh.numVerts;

    //  copy vertices
    for (int i = 0; i < numVert; i++)
    {
        Point3 pt   = mesh.verts[i];
        pt = mOffs.PointTransform( pt );
        pt = c_FlipTM.PointTransform( pt );
        pMesh->AddVertex( Vec3( pt.x, pt.y, pt.z ) );
    }

    //  loop on mesh faces
    for (int i = 0; i < numPri; i++)
    {
        Face& face = mesh.faces[i];
        pMesh->AddPoly( face.v[vx[0]], face.v[vx[1]], face.v[vx[2]] );
    }

    Msg( LogType_Stats, "Physics collision trimesh has %d vertices and %d faces.", numVert, numPri );

    return pMesh;
} // RBExport::GetColMesh
示例#12
0
文件: mesh.cpp 项目: skopp/rush
//  Here we process mesh geometry for given node.
//  Vertices for the geometry from the all meshes of the scene are allocated in 
//  one big vertex pool. One vertex can occur several times in this pool, because
//  we add 3 new vertices for every face.
//  After all meshes in the scene are processed, this pool is collapsed to remove
//  duplicate vertices.
void RBExport::ProcessMesh( INode* node )
{
    if (!node->Renderable() || node->IsNodeHidden())
    {
        return;
    }
    
    ObjectState os      = node->EvalWorldState( m_CurTime );
    Object*     pObject = os.obj;
    if (!pObject) 
    {
        Warn( "Could not evaluate object state in node <%s>. Mesh was skipped.", node->GetName() );
        return;
    }
    Matrix3 nodeTM          = node->GetNodeTM( m_CurTime );
    Matrix3 nodeTMAfterWSM  = node->GetObjTMAfterWSM( m_CurTime );
    Matrix3 mOffs           = nodeTMAfterWSM*Inverse( nodeTM );

    //  triangulate
    TriObject* pTriObj = 0;
    if (pObject->CanConvertToType( Class_ID( TRIOBJ_CLASS_ID, 0 ) )) 
    { 
        pTriObj = (TriObject*)pObject->ConvertToType( m_CurTime, Class_ID( TRIOBJ_CLASS_ID, 0 ) );
    }
    bool bReleaseTriObj = (pTriObj != pObject);
    if (!pTriObj) 
    {
        Warn( "Could not triangulate mesh in node <%s>. Node was skipped", node->GetName() );
        return;
    }

    if (!MeshModStackIsValid( node ))
    {
        Warn( "Modifier stack for node %s should be collapsed or contain only Skin modifier.", 
                node->GetName() );
    }

    //  ensure, that vertex winding direction in polygon is CCW
    Matrix3 objTM = node->GetObjTMAfterWSM( m_CurTime );
    bool bNegScale = (DotProd( CrossProd( objTM.GetRow(0), objTM.GetRow(1) ), objTM.GetRow(2) ) >= 0.0);

    int vx[3];
    if (bNegScale) 
    {
        vx[0] = 0; 
        vx[1] = 1; 
        vx[2] = 2; 
    } 
    else 
    { 
        vx[0] = 2; 
        vx[1] = 1; 
        vx[2] = 0; 
    }

    Mesh& mesh = pTriObj->GetMesh();

    bool bHasTexCoord    = (mesh.numTVerts != 0);
    bool bHasVertexColor = (mesh.numCVerts != 0) && m_pConfig->m_bExportVertexColors;
    bool bHasNormal      = m_pConfig->m_bExportNormals; 
    bool bHasSkin        = ProcessSkin( node );

    //  some cosmetics
    BOOL res = mesh.RemoveDegenerateFaces();
    if (res) 
    {
        Spam( "Degenerate faces were fixed." );
    }

    res = mesh.RemoveIllegalFaces();
    if (res) 
    {
        Spam( "Degenerate indices were fixed." );
    }
    
    ExpNode* pExpNode = GetExportedNode( node );
    if (!pExpNode)
    {
        return;
    }

    int numPri     = mesh.getNumFaces();
    int numVert    = mesh.numVerts;

    //  initialize helper array for building vertices' 0-circles
    VertexPtrArray vertexEntry;
    vertexEntry.resize( numVert );
    memset( &vertexEntry[0], 0, sizeof( ExpVertex* )*numVert );

    Spam( "Original mesh has %d vertices and %d faces.", numVert, numPri );
    bool bHasVoidFaces = false;

    //  loop on mesh faces
    for (int i = 0; i < numPri; i++)
    {
        Face& face = mesh.faces[i];

        //  calculate face normal
        const Point3& v0 = mesh.verts[face.v[vx[0]]]; 
        const Point3& v1 = mesh.verts[face.v[vx[1]]]; 
        const Point3& v2 = mesh.verts[face.v[vx[2]]]; 
        Point3 normal = -Normalize( (v1 - v0)^(v2 - v1) ); 
        normal = mOffs.VectorTransform( normal );
        normal = c_FlipTM.VectorTransform( normal );

        //  loop on face vertices
        ExpVertex* pFaceVertex[3];
        for (int j = 0; j < 3; j++)
        {
            ExpVertex v;
            v.mtlID  = pExpNode->GetMaterialIdx( face.getMatID() );            
            v.nodeID = pExpNode->m_Index;

            if (v.mtlID < 0)
            {
                bHasVoidFaces = true;
            }
            
            //  extract vertex position and apply world-space modifier to it
            int vIdx    = face.v[vx[j]];
            Point3 pt   = mesh.verts[vIdx];
            pt = mOffs.PointTransform( pt );
            pt = c_FlipTM.PointTransform( pt );
            
            v.index = vIdx;
            v.pos   = Vec3( pt.x, pt.y, pt.z );
            //v.pos *= m_WorldScale;

            //  extract skinning info
            if (bHasSkin)
            {
                GetSkinInfo( v );
            }

            //  assign normal
            if (bHasNormal)
            {
                v.normal  = Vec3( normal.x, normal.y, normal.z );
                v.smGroup = face.smGroup;
            }
            
            //  extract vertex colors
            if (bHasVertexColor)    
            {
                const VertColor& vcol = mesh.vertCol[mesh.vcFace[i].t[vx[j]]];
                v.color = ColorToDWORD( Color( vcol.x, vcol.y, vcol.z ) );
            }

            //  extract texture coordinates
            if (bHasTexCoord)   
            {
                const Point3& texCoord = mesh.tVerts[mesh.tvFace[i].t[vx[j]]];
                v.uv.x = texCoord.x;
                v.uv.y = 1.0f - texCoord.y;

                //  second texture coordinate channel
                if (mesh.getNumMaps() > 1 && mesh.mapSupport( 2 ))
                {
                    UVVert* pUVVert = mesh.mapVerts( 2 );
                    TVFace* pTVFace = mesh.mapFaces( 2 );
                    if (pUVVert && pTVFace)
                    {
                        const Point3& tc2 = pUVVert[pTVFace[i].t[vx[j]]];
                        v.uv2.x = tc2.x;
                        v.uv2.y = 1.0f - tc2.y;
                    }
                }
            }

            //  allocate new vertex 
            pFaceVertex[j] = AddVertex( v );

            //  we want vertices in the 0-ring neighborhood to be linked into closed linked list
            if (vertexEntry[vIdx] == NULL) 
            {
                vertexEntry[vIdx] = pFaceVertex[j];
                pFaceVertex[j]->pNext = pFaceVertex[j];
            }
            else
            {
                vertexEntry[vIdx]->AddToZeroRing( pFaceVertex[j] );
            }
        }
        AddPolygon( pFaceVertex[0], pFaceVertex[1], pFaceVertex[2] );

        if (IsCanceled())
        {
            return;
        }
    }

    //  correct normals at vertices corresponding to smoothing groups
    SmoothNormals( vertexEntry );

    //  put vertices into set (this removes duplicate vertices)
    for (int i = 0; i < numVert; i++)
    {
        ExpVertex::ZeroRingIterator it( vertexEntry[i] );
        while (it)
        {
            VertexSet::iterator sIt = m_VertexSet.find( it );
            if (sIt == m_VertexSet.end())
            {
                m_VertexSet.insert( it );
            }
            else
            {
                it->pBase = (*sIt);
            }
            ++it;
        }
    }

    if (bReleaseTriObj) 
    {
        delete pTriObj;
    }

    if (bHasVoidFaces)
    {
        Warn( "Mesh %s has faces with no material assigned.", node->GetName() );
    }
} // RBExport::ProcessMesh
void CompressibleNonlinearElasticitySolver<DIM>::AssembleOnElement(
            Element<DIM, DIM>& rElement,
            c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElem,
            c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElemPrecond,
            c_vector<double, STENCIL_SIZE>& rBElem,
            bool assembleResidual,
            bool assembleJacobian)
{
    static c_matrix<double,DIM,DIM> jacobian;
    static c_matrix<double,DIM,DIM> inverse_jacobian;
    double jacobian_determinant;

    this->mrQuadMesh.GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);

    if (assembleJacobian)
    {
        rAElem.clear();
        rAElemPrecond.clear();
    }

    if (assembleResidual)
    {
        rBElem.clear();
    }

    // Get the current displacement at the nodes
    static c_matrix<double,DIM,NUM_NODES_PER_ELEMENT> element_current_displacements;
    for (unsigned II=0; II<NUM_NODES_PER_ELEMENT; II++)
    {
        for (unsigned JJ=0; JJ<DIM; JJ++)
        {
            element_current_displacements(JJ,II) = this->mCurrentSolution[DIM*rElement.GetNodeGlobalIndex(II) + JJ];
        }
    }

    // Allocate memory for the basis functions values and derivative values
    static c_vector<double, NUM_VERTICES_PER_ELEMENT> linear_phi;
    static c_vector<double, NUM_NODES_PER_ELEMENT> quad_phi;
    static c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> grad_quad_phi;
    static c_matrix<double, NUM_NODES_PER_ELEMENT, DIM> trans_grad_quad_phi;

    // Get the material law
    AbstractCompressibleMaterialLaw<DIM>* p_material_law
       = this->mrProblemDefinition.GetCompressibleMaterialLaw(rElement.GetIndex());


    static c_matrix<double,DIM,DIM> grad_u; // grad_u = (du_i/dX_M)

    static c_matrix<double,DIM,DIM> F;      // the deformation gradient, F = dx/dX, F_{iM} = dx_i/dX_M
    static c_matrix<double,DIM,DIM> C;      // Green deformation tensor, C = F^T F
    static c_matrix<double,DIM,DIM> inv_C;  // inverse(C)
    static c_matrix<double,DIM,DIM> inv_F;  // inverse(F)
    static c_matrix<double,DIM,DIM> T;      // Second Piola-Kirchoff stress tensor (= dW/dE = 2dW/dC)

    static c_matrix<double,DIM,DIM> F_T;    // F*T
    static c_matrix<double,DIM,NUM_NODES_PER_ELEMENT> F_T_grad_quad_phi; // F*T*grad_quad_phi

    c_vector<double,DIM> body_force;

    static FourthOrderTensor<DIM,DIM,DIM,DIM> dTdE;    // dTdE(M,N,P,Q) = dT_{MN}/dE_{PQ}
    static FourthOrderTensor<DIM,DIM,DIM,DIM> dSdF;    // dSdF(M,i,N,j) = dS_{Mi}/dF_{jN}

    static FourthOrderTensor<NUM_NODES_PER_ELEMENT,DIM,DIM,DIM> temp_tensor;
    static FourthOrderTensor<NUM_NODES_PER_ELEMENT,DIM,NUM_NODES_PER_ELEMENT,DIM> dSdF_quad_quad;

    static c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> temp_matrix;
    static c_matrix<double,NUM_NODES_PER_ELEMENT,DIM> grad_quad_phi_times_invF;

    if(this->mSetComputeAverageStressPerElement)
    {
        this->mAverageStressesPerElement[rElement.GetIndex()] = zero_vector<double>(DIM*(DIM+1)/2);
    }

    // Loop over Gauss points
    for (unsigned quadrature_index=0; quadrature_index < this->mpQuadratureRule->GetNumQuadPoints(); quadrature_index++)
    {
        // This is needed by the cardiac mechanics solver
        unsigned current_quad_point_global_index =   rElement.GetIndex()*this->mpQuadratureRule->GetNumQuadPoints()
                                                   + quadrature_index;

        double wJ = jacobian_determinant * this->mpQuadratureRule->GetWeight(quadrature_index);

        const ChastePoint<DIM>& quadrature_point = this->mpQuadratureRule->rGetQuadPoint(quadrature_index);

        // Set up basis function information
        LinearBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, linear_phi);
        QuadraticBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, quad_phi);
        QuadraticBasisFunction<DIM>::ComputeTransformedBasisFunctionDerivatives(quadrature_point, inverse_jacobian, grad_quad_phi);
        trans_grad_quad_phi = trans(grad_quad_phi);

        // Get the body force, interpolating X if necessary
        if (assembleResidual)
        {
            switch (this->mrProblemDefinition.GetBodyForceType())
            {
                case FUNCTIONAL_BODY_FORCE:
                {
                    c_vector<double,DIM> X = zero_vector<double>(DIM);
                    // interpolate X (using the vertices and the /linear/ bases, as no curvilinear elements
                    for (unsigned node_index=0; node_index<NUM_VERTICES_PER_ELEMENT; node_index++)
                    {
                        X += linear_phi(node_index)*this->mrQuadMesh.GetNode( rElement.GetNodeGlobalIndex(node_index) )->rGetLocation();
                    }
                    body_force = this->mrProblemDefinition.EvaluateBodyForceFunction(X, this->mCurrentTime);
                    break;
                }
                case CONSTANT_BODY_FORCE:
                {
                    body_force = this->mrProblemDefinition.GetConstantBodyForce();
                    break;
                }
                default:
                    NEVER_REACHED;
            }
        }

        // Interpolate grad_u
        grad_u = zero_matrix<double>(DIM,DIM);
        for (unsigned node_index=0; node_index<NUM_NODES_PER_ELEMENT; node_index++)
        {
            for (unsigned i=0; i<DIM; i++)
            {
                for (unsigned M=0; M<DIM; M++)
                {
                    grad_u(i,M) += grad_quad_phi(M,node_index)*element_current_displacements(i,node_index);
                }
            }
        }

        // Calculate C, inv(C) and T
        for (unsigned i=0; i<DIM; i++)
        {
            for (unsigned M=0; M<DIM; M++)
            {
                F(i,M) = (i==M?1:0) + grad_u(i,M);
            }
        }

        C = prod(trans(F),F);
        inv_C = Inverse(C);
        inv_F = Inverse(F);

        // Compute the passive stress, and dTdE corresponding to passive stress
        this->SetupChangeOfBasisMatrix(rElement.GetIndex(), current_quad_point_global_index);
        p_material_law->SetChangeOfBasisMatrix(this->mChangeOfBasisMatrix);
        p_material_law->ComputeStressAndStressDerivative(C, inv_C, 0.0, T, dTdE, assembleJacobian);

        if(this->mIncludeActiveTension)
        {
            // Add any active stresses, if there are any. Requires subclasses to overload this method,
            // see for example the cardiac mechanics assemblers.
            this->AddActiveStressAndStressDerivative(C, rElement.GetIndex(), current_quad_point_global_index,
                                                     T, dTdE, assembleJacobian);
        }

        if(this->mSetComputeAverageStressPerElement)
        {
            this->AddStressToAverageStressPerElement(T,rElement.GetIndex());
        }

        // Residual vector
        if (assembleResidual)
        {
            F_T = prod(F,T);
            F_T_grad_quad_phi = prod(F_T, grad_quad_phi);

            for (unsigned index=0; index<NUM_NODES_PER_ELEMENT*DIM; index++)
            {
                unsigned spatial_dim = index%DIM;
                unsigned node_index = (index-spatial_dim)/DIM;

                rBElem(index) += - this->mrProblemDefinition.GetDensity()
                                 * body_force(spatial_dim)
                                 * quad_phi(node_index)
                                 * wJ;

                // The T(M,N)*F(spatial_dim,M)*grad_quad_phi(N,node_index) term
                rBElem(index) +=   F_T_grad_quad_phi(spatial_dim,node_index)
                                 * wJ;
            }
        }

        // Jacobian matrix
        if (assembleJacobian)
        {
            // Save trans(grad_quad_phi) * invF
            grad_quad_phi_times_invF = prod(trans_grad_quad_phi, inv_F);

            /////////////////////////////////////////////////////////////////////////////////////////////
            // Set up the tensor dSdF
            //
            // dSdF as a function of T and dTdE (which is what the material law returns) is given by:
            //
            // dS_{Mi}/dF_{jN} = (dT_{MN}/dC_{PQ}+dT_{MN}/dC_{PQ}) F{iP} F_{jQ}  + T_{MN} delta_{ij}
            //
            // todo1: this should probably move into the material law (but need to make sure
            // memory is handled efficiently
            // todo2: get material law to return this immediately, not dTdE
            /////////////////////////////////////////////////////////////////////////////////////////////

            // Set up the tensor 0.5(dTdE(M,N,P,Q) + dTdE(M,N,Q,P))
            for (unsigned M=0; M<DIM; M++)
            {
                for (unsigned N=0; N<DIM; N++)
                {
                    for (unsigned P=0; P<DIM; P++)
                    {
                        for (unsigned Q=0; Q<DIM; Q++)
                        {
                            // this is NOT dSdF, just using this as storage space
                            dSdF(M,N,P,Q) = 0.5*(dTdE(M,N,P,Q) + dTdE(M,N,Q,P));
                        }
                    }
                }
            }

            // This is NOT dTdE, just reusing memory. A^{MdPQ}  = F^d_N * dTdE_sym^{MNPQ}
            dTdE.template SetAsContractionOnSecondDimension<DIM>(F, dSdF);

            // dSdF{MdPe} := F^d_N * F^e_Q * dTdE_sym^{MNPQ}
            dSdF.template SetAsContractionOnFourthDimension<DIM>(F, dTdE);

            // Now add the T_{MN} delta_{ij} term
            for (unsigned M=0; M<DIM; M++)
            {
                for (unsigned N=0; N<DIM; N++)
                {
                    for (unsigned i=0; i<DIM; i++)
                    {
                        dSdF(M,i,N,i) += T(M,N);
                    }
                }
            }

            ///////////////////////////////////////////////////////
            // Set up the tensor
            //   dSdF_quad_quad(node_index1, spatial_dim1, node_index2, spatial_dim2)
            //            =    dS_{M,spatial_dim1}/d_F{spatial_dim2,N}
            //               * grad_quad_phi(M,node_index1)
            //               * grad_quad_phi(P,node_index2)
            //
            //            =    dSdF(M,spatial_index1,N,spatial_index2)
            //               * grad_quad_phi(M,node_index1)
            //               * grad_quad_phi(P,node_index2)
            //
            ///////////////////////////////////////////////////////
            temp_tensor.template SetAsContractionOnFirstDimension<DIM>(trans_grad_quad_phi, dSdF);
            dSdF_quad_quad.template SetAsContractionOnThirdDimension<DIM>(trans_grad_quad_phi, temp_tensor);

            for (unsigned index1=0; index1<NUM_NODES_PER_ELEMENT*DIM; index1++)
            {
                unsigned spatial_dim1 = index1%DIM;
                unsigned node_index1 = (index1-spatial_dim1)/DIM;

                for (unsigned index2=0; index2<NUM_NODES_PER_ELEMENT*DIM; index2++)
                {
                    unsigned spatial_dim2 = index2%DIM;
                    unsigned node_index2 = (index2-spatial_dim2)/DIM;

                    // The dSdF*grad_quad_phi*grad_quad_phi term
                    rAElem(index1,index2) +=   dSdF_quad_quad(node_index1,spatial_dim1,node_index2,spatial_dim2)
                                             * wJ;
                }
            }
        }
    }

    rAElemPrecond.clear();
    if (assembleJacobian)
    {
        rAElemPrecond = rAElem;
    }

    if(this->mSetComputeAverageStressPerElement)
    {
        for(unsigned i=0; i<DIM*(DIM+1)/2; i++)
        {
            this->mAverageStressesPerElement[rElement.GetIndex()](i) /= this->mpQuadratureRule->GetNumQuadPoints();
        }
    }

}
示例#14
0
文件: MYAPPR_P.CPP 项目: pyal/eos_cpp
//typedef double* FOOL;
int MAPGetDir(double *Param,double *MaxStep,MatrCl &DirMat,double ErrorMatr) 
  {
//cout<<"   MAPGetDir  Begin  \n";
   int Dimen=Param[0],DimExp=(*MAPVar).ExperPoint[0],Ret=1;
   if ((Dimen>0) && (DimExp>0))
     {
      int k,k1;
      int Iter;
      VecCl TmpGr(DimExp),CurGr(DimExp);
      VecCl HiGrad(Dimen);
      MatrCl WMat1(Dimen),WMat2(Dimen);
      double TmpHi,CurHi=True_Hi(Param); 
//cout<<" Coreleft MAPDir "<<coreleft()<<"\n";
      double *TmpPar=new double[Dimen+1];
      double *NormDiag=new double[Dimen+1];
      VecCl *GrDat=new VecCl[Dimen+1];
      for (k=1;k<=Dimen;k++) GrDat[k].SetDim(DimExp);

      True_Gr(Param,CurGr.Ptr);
// begining of calculation of d(hi)/dx[k] in HiGrad[k]
//cout<<" Coreleft 90     "<<coreleft()<<"\n";
      for (k=1;k<=Dimen;k++)
        {
if (fabs(MaxStep[k])<MathZer) cout<<" MAPGetDir MaxStep k "<<MaxStep[k]<<"  "<<k<<"\n";
         movmem(Param,TmpPar,sizeof(double)*(Dimen+1));
         TmpPar[k]+=DERIVESTP*MaxStep[k];
         True_Gr(TmpPar,TmpGr.Ptr);
         for (k1=1;k1<=DimExp;k1++) 
           GrDat[k][k1]=(TmpGr[k1]-CurGr[k1])/(DERIVESTP*MaxStep[k]);
         TmpHi=True_Hi(TmpPar);
         HiGrad[k]=(CurHi-TmpHi)/(DERIVESTP*MaxStep[k]);
        }
//cout<<" Hi Grad "<<HiGrad<<"Cur_Hi "<<CurHi<<"\nMax Step ";
//      for (k=1;k<=Dimen;k++) cout<<MaxStep[k]<<"  ";cout<<"\n";
//ChRead();
//
//     end of calculation of d(hi)/dx[k] in HiGrad[k]}
//
//{ begining of calculation d(integral(dx[i]))/dx[k]=hmat[i,k]
//                                       D'[k]=correl[k]               }
      for (k=1;k<=Dimen;k++)
        {
         for (k1=k;k1<=Dimen;k1++) 
            WMat1(k,k1)=Correl_Func(DimExp,GrDat[k].Ptr,GrDat[k1].Ptr);
         if (WMat1(k,k)<MathZer) 
           {cout<<" Function does not depend from parameter "<<k<<". Exiting\n";
            Ret=0;goto exi;
           }
         double d=sqrt(WMat1(k,k));
if (d<MathZer) cout<<" MAPGetDir sqrt(WMat1(k,k)) k "<<d<<"  "<<k<<"\n";
         NormDiag[k]=1/d;//sqrt(WMat1(k,k));
        }
//cout<<" dxi/dxk \n"<<WMat1;
      for ( k=1;k<=Dimen;k++)
       { 
        for (k1=k;k1<=Dimen;k1++)
          {
           WMat1(k,k1)=WMat1(k,k1)*NormDiag[k]*NormDiag[k1];
           WMat1(k1,k)=WMat1(k,k1);
          }
       } 
//cout<<" dxi/dxk normalized\n"<<WMat1;
//  fwritem(nomparam,addr(hmat),1,1);k0:=ermes('first converted',-1);
//{ end      of calculation d(integral(dx[i]))/dx[k]=hmat[i,k]
//                                       D'[k,k]=correl[k]               }
//cout<<" Coreleft 129    "<<coreleft()<<"\n";

//      if ((Err=Jacobi(WMat1,1000,ErrorMatr,TmpPar,WMat1,Iter))!=0) 
//        {cout<<" Cannot Calculate Jacobi. Error ="<<Err<<" \n";exit(1);}
      if (!ReduceLQ(WMat1,WMat1,TmpPar,ErrorMatr)) 
        {cout<<" Cannot Calculate ReduceLQ. \n";Ret=0;goto exi;}
//cout<<" Coreleft 132=129"<<coreleft()<<"\n";
//cout<<" Eigen Vectors\n"<<WMat1<<" Eigen Val \n";ChRead();
//for ( k=1;k<=Dimen;k++) cout<<TmpPar[k]<<"   ";cout<<"\n";
      
//      Transpon(WMat1);  //Because ReduceLQ we have not to transpon
      WMat2=WMat1;
//cout<<" Coreleft 137    "<<coreleft()<<"\n";
//cout<<"Inverse ";
      Inverse(WMat1);
//cout<<" O Key \n";
//cout<<" Coreleft 139=137"<<coreleft()<<"\n";
      for ( k=1;k<=Dimen;k++)
       { 
        for ( k1=1;k1<=Dimen;k1++)
          {
         double d=sqrt(fabs(TmpPar[k1]));
if (d<MathZer) cout<<" MAPGetDir sqrt(fabs(TmpPar[k1])) k1 "<<d<<"  "<<k1<<"\n";
           WMat2(k,k1)=WMat2(k,k1)/d;//sqrt(fabs(TmpPar[k1]));
          } 
       } 
      WMat1=WMat2*WMat1;
//cout<< " Result Matr After Mull\n"<<WMat1;
      for ( k=1;k<=Dimen;k++)
       { 
        for ( k1=1;k1<=Dimen;k1++)
           WMat1(k,k1)=WMat1(k,k1)*NormDiag[k];
       } 
//cout<<" MaxStep: ";
      for ( k=1;k<=Dimen;k++)
       { 
        double s=0;
        for (int k1=1;k1<=Dimen;k1++)  s+=HiGrad[k1]*WMat1(k1,k);
        MaxStep[k]=s;
//cout<<MaxStep[k]<<"  ";
       } 
//cout<<"\n";
//ChRead();
//cout<<" Coreleft 158=90    "<<coreleft()<<"\n";
      DirMat=WMat1;
//cout<<" Coreleft 160 "<<coreleft()<<"\n";
//cout<< " Dir  Matr \n"<<DirMat;
//cout<<"MaxStep ";for (k=1;k<=Dimen;k++) cout<<MaxStep[k]<<"  ";cout<<"\n";
  exi:
    delete TmpPar;
    delete NormDiag;
    for ( k=0;k<=Dimen;k++)  {delete GrDat[k].Ptr;GrDat[k].Ptr=NULL;}
    delete GrDat;
//cout<< "End  MAPGetDir\n";
//cout<<" Coreleft MAPDir "<<coreleft()<<"\n";
   }
  return Ret;
 };
Matrix3 plMaxNodeBase::GetLocalToVert(TimeValue t)
{
    Matrix3 v2l = GetVertToLocal(t);
    Matrix3 l2v = Inverse(v2l);
    return l2v;
}
示例#16
0
//----------------------------------------------------------------------------
PX2::Transform SceneBuilder::GetLocalTransform (INode *node, TimeValue time)
{
	// 计算节点的本地变换。Max节点的变换方法提供的节点的世界变换,所以我们
	// 必须做一些操纵去获得节点的本地变换。

	Matrix3 maxLocal = node->GetObjTMAfterWSM(time) *
		Inverse(node->GetParentNode()->GetObjTMAfterWSM(time));

	// 分解变换
	AffineParts affParts;
	decomp_affine(maxLocal, &affParts);

	// Position
	bool isTranslationZero = 
		fabsf(affParts.t.x) < MIN_DIFFERENCE &&
		fabsf(affParts.t.y) < MIN_DIFFERENCE &&
		fabsf(affParts.t.z) < MIN_DIFFERENCE;

	// Rotation
	float qSign = (affParts.q.w >= 0.0f ? 1.0f : -1.0f);
	bool isRotationIndentity = 
		fabsf(qSign*affParts.q.w - 1.0f) < MIN_DIFFERENCE &&
		fabsf(affParts.q.x) < MIN_DIFFERENCE &&
		fabsf(affParts.q.y) < MIN_DIFFERENCE &&
		fabsf(affParts.q.z) < MIN_DIFFERENCE;

	// Reflect
	bool hasReflection = (affParts.f < 0.0f);

	// Uniform scale
	bool isScaleUniform = (fabsf(affParts.k.x - affParts.k.y)<MIN_DIFFERENCE &&
		fabsf(affParts.k.y - affParts.k.z)<MIN_DIFFERENCE);

	// Unity scale
	bool isScaleUnity = isScaleUniform &&
		fabsf(affParts.k.x - 1.0f) < MIN_DIFFERENCE;

	// Scale orientation is identity?
	float uSign = (affParts.u.w >= 0.0f ? 1.0f : -1.0f);
	bool isOrientIndentity = isScaleUniform || (
		fabsf(uSign*affParts.u.w - 1.0f) < MIN_DIFFERENCE &&
		fabsf(affParts.u.x) < MIN_DIFFERENCE &&
		fabsf(affParts.u.y) < MIN_DIFFERENCE &&
		fabsf(affParts.u.z) < MIN_DIFFERENCE);

	// 计算Phoenix2等价变换
	PX2::Transform local;

	if (!isTranslationZero)
	{
		local.SetTranslate(PX2::APoint(affParts.t.x, affParts.t.y,
			affParts.t.z));
	}

	if (hasReflection)
	{
		affParts.k *= -1.0f;
	}
	
	if (isScaleUniform)
	{
		// 矩阵的形式为R*(s*I),s是统一缩放矩阵。
		if (!isRotationIndentity)
		{
			PX2::HMatrix rot;
			PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y,
				-affParts.q.z).ToRotationMatrix(rot);
			local.SetRotate(rot);
		}

		if (!isScaleUnity)
		{
			local.SetUniformScale(affParts.k.x);
		}
	}
	else if (isOrientIndentity)
	{
		if (!isRotationIndentity)
		{
			PX2::HMatrix rot;
			PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y,
				-affParts.q.z).ToRotationMatrix(rot);
			local.SetRotate(rot);
		}

		local.SetScale(PX2::APoint(affParts.k.x, affParts.k.y, affParts.k.z));
	}
	else
	{
		PX2::Matrix3f mat(
			maxLocal.GetAddr()[0][0],
			maxLocal.GetAddr()[1][0],
			maxLocal.GetAddr()[2][0],
			maxLocal.GetAddr()[0][1],
			maxLocal.GetAddr()[1][1],
			maxLocal.GetAddr()[2][1],
			maxLocal.GetAddr()[0][2],
			maxLocal.GetAddr()[1][2],
			maxLocal.GetAddr()[2][2]);

		local.SetMatrix(PX2::HMatrix(mat));
	}

	return local;
}
Matrix3 plMaxNodeBase::GetOBBToLocal(TimeValue t)
{
    return Inverse(GetOTM(t)) * GetVertToLocal(t);
}
示例#18
0
void LocalInverse( DistMatrix<F,STAR,STAR>& A )
{
    DEBUG_CSE
    Inverse( A.Matrix() );
}
示例#19
0
void GradientDataExport<dim>::eval_and_deriv(MathVector<dim> vValue[],
                    const MathVector<dim> vGlobIP[],
                    number time, int si,
                    GridObject* elem,
                    const MathVector<dim> vCornerCoords[],
                    const MathVector<refDim> vLocIP[],
                    const size_t nip,
                    LocalVector* u,
                    bool bDeriv,
                    int s,
                    std::vector<std::vector<MathVector<dim> > > vvvDeriv[],
                    const MathMatrix<refDim, dim>* vJT) const
{
//	abbreviation for component
	static const int _C_ = 0;

//	reference object id
	const ReferenceObjectID roid = elem->reference_object_id();

//	local finite element id
	const LFEID& lfeID = this->function_group().local_finite_element_id(_C_);

//	access local vector by map
	u->access_by_map(this->map());

//	request for trial space
	try{
	const LocalShapeFunctionSet<refDim>& rTrialSpace
		 = LocalFiniteElementProvider::get<refDim>(roid, lfeID);

//	Reference Mapping
	MathMatrix<dim, refDim> JTInv;
	std::vector<MathMatrix<refDim, dim> > vJTtmp;
	if(!vJT){
		DimReferenceMapping<refDim, dim>& map
			= ReferenceMappingProvider::get<refDim, dim>(roid, vCornerCoords);

		vJTtmp.resize(nip);
		map.jacobian_transposed(&vJTtmp[0], vLocIP, nip);
		vJT = &vJTtmp[0];
	}

//	storage for shape function at ip
	std::vector<MathVector<refDim> > vLocGrad;
	MathVector<refDim> locGrad;

//	loop ips
	for(size_t ip = 0; ip < nip; ++ip)
	{
	//	evaluate at shapes at ip
		rTrialSpace.grads(vLocGrad, vLocIP[ip]);

	//	compute grad at ip
		VecSet(locGrad, 0.0);
		for(size_t sh = 0; sh < vLocGrad.size(); ++sh)
			VecScaleAppend(locGrad, (*u)(_C_, sh), vLocGrad[sh]);

		Inverse(JTInv, vJT[ip]);
		MatVecMult(vValue[ip], JTInv, locGrad);

	//	store derivative
		if(bDeriv)
			for(size_t sh = 0; sh < vLocGrad.size(); ++sh)
				MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]);
	}

	}
	UG_CATCH_THROW("GradientDataExport: Trial space missing, Reference Object: "
				 <<roid<<", Trial Space: "<<lfeID<<", refDim="<<refDim);
}
示例#20
0
/*
====================
GatherSkin
====================
*/
void G3DSExport::GatherSkin(INode* i_node)
{
	SKIN skin;

	// get the name of the node
	skin.name = i_node->GetName();

	// get the skin interface
	Modifier *modifier = GetModifier(i_node,SKIN_CLASSID);
	ISkin* i_skin = (ISkin*)modifier->GetInterface(I_SKIN);
	MAX_CHECK(i_skin);

	// convert to the triangle type
	Mesh* i_mesh = NULL;
	Object* obj = i_node->EvalWorldState(mTime).obj;
	if(obj && ( obj->SuperClassID() == GEOMOBJECT_CLASS_ID ))
	{
		if(obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) 
		{ 
			TriObject *tri_obj = (TriObject*)obj->ConvertToType(mTime, Class_ID(TRIOBJ_CLASS_ID, 0)); MAX_CHECK(tri_obj);
			i_mesh = &tri_obj->mesh;
		}
	}
	MAX_CHECK(i_mesh&&i_mesh->getNumFaces()&&i_mesh->getNumVerts());

	// get the material
	skin.texture = "textures/default.tga";
	Mtl* mtl = i_node->GetMtl();
	if(mtl && (mtl->ClassID()==Class_ID(DMTL_CLASS_ID, 0)) && ((StdMat*)mtl)->MapEnabled(ID_DI)) 
	{
		Texmap *texmap = mtl->GetSubTexmap(ID_DI);
		if(texmap && texmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
		{
			skin.texture = UnifySlashes(((BitmapTex *)texmap)->GetMapName());
			if( !strstr( skin.texture.c_str(), mPath.c_str() ) )
			{
				G3DAssert("The material(%s) is error : the texture path(%s) is illegal!",mtl->GetName(), skin.texture.c_str());
			}
			else
			{
				skin.texture = strstr(skin.texture.c_str(),mPath.c_str()) + strlen(mPath.c_str());
			}
		}
	}

	// if it has uvs
	int map_count = i_mesh->getNumMaps();
	bool has_uvs = i_mesh->getNumTVerts() && i_mesh->tvFace;
	if(!(has_uvs&&map_count)) { G3DAssert("The skin(%s) has not the uv coordinates.",skin.name.c_str()); return; }

	// get the transform
	Matrix3 mesh_matrix = i_node->GetObjectTM(mTime);
	Matrix3 node_matrix = i_node->GetNodeTM(mTime);
	Matrix3 transform = mesh_matrix * Inverse(node_matrix);

	// get the points
	skin.points.assign(i_mesh->verts, i_mesh->verts+i_mesh->getNumVerts());

	// get the triangles
	for(int i = 0; i < i_mesh->getNumFaces(); i++)
	{
		Face& face = i_mesh->faces[i];

		TRIANGLE tri;		
		tri.smoothing = face.smGroup;
		for(int j = 0; j < 3; j++)
		{
			VPTNIS v;
			v.pos = transform * i_mesh->verts[face.v[j]];

			// get the uv
			UVVert * map_verts = i_mesh->mapVerts(1);
			TVFace * map_faces = i_mesh->mapFaces(1);
			v.uv = reinterpret_cast<Point2&>(map_verts[map_faces[i].t[j]]);
			v.uv.y = 1 - v.uv.y;

			// initialize the normal
			v.normal = Point3::Origin;

			// get the vertex index
			v.index = face.v[j];

			// get the smoothing group
			v.smoothing = face.smGroup;			

			// set the index for the triangle
			tri.index0[j] = v.index;

			// reassemble the vertex list
			tri.index1[j] = AddVertex(skin, v);
		}

		// add the triangle to the table
		skin.triangles.push_back(tri);
	}

	// build the index map
	for( int i = 0; i < skin.vertexes.size(); i++ )
	{
		skin.vertex_index_map[skin.vertexes[i].index].push_back(i);
	}

	// get the skin context data
	ISkinContextData* i_skin_context_data = i_skin->GetContextInterface(i_node);
	if(i_skin_context_data == NULL) { G3DAssert("The skin(%s) has not the weight.",skin.name.c_str()); return; }

	// gets the initial matrix of the skinned object 
	Matrix3 initial_object_transform;
	i_skin->GetSkinInitTM(i_node, initial_object_transform, true);

	// process the points
	int num_points = i_skin_context_data->GetNumPoints();
	for(int i = 0; i < num_points; i++)
	{
		MAX_CHECK(i < skin.points.size());

		VPIW viw;

		// get the initial point				
		viw.pos = initial_object_transform * skin.points[i];

		// process the weights		
		std::multimap< float, int > weights;

		// get the number of bones that control this vertex
		int num_bones = i_skin_context_data->GetNumAssignedBones(i);
		if(num_bones>0)
		{
			for (int j = 0; j < num_bones; j++)
			{
				Matrix3 transform;

				// get the assigned bone of the point 
				INode* i_bone_node = i_skin->GetBone(i_skin_context_data->GetAssignedBone(i, j));
				MAX_CHECK(i_bone_node != NULL);

				// get the weight of the bone
				float weight = i_skin_context_data->GetBoneWeight(i, j);

				// add the weight to the table
				weights.insert(std::make_pair(weight, AddBone(skin,i_bone_node)));
			}
		}
		else
		{
			// add the weight to the table
			weights.insert(std::make_pair(1.f, AddBone(skin,i_node)));
		}

		// recalculate the weights
		float weight0 = 0.f, weight1 = 0.f, weight2 = 0.f;
		int index0 = 0, index1 = 0, index2 = 0;
		std::multimap< float, int >::iterator it = weights.end();
		it--;
		weight0 = it->first;
		index0 = it->second;
		if(it != weights.begin())
		{
			it--;
			weight1 = it->first;
			index1 = it->second;
			if(it != weights.begin())
			{
				it--;
				weight2 = it->first;
				index2 = it->second;
			}
		}		
		float sum_weights = weight0 + weight1 + weight2;

		// store the skin weights	
		viw.weight[0]	= weight0/sum_weights;
		viw.index[0]	= index0;
		viw.weight[1]	= weight1/sum_weights;
		viw.index[1]	= index1;
		viw.weight[2]	= weight2/sum_weights;
		viw.index[2]	= index2;
		skin.weights.push_back(viw);
	}

	// get the initial transforms
	skin.transforms.resize(skin.bones.size());
	for(int i = 0; i < skin.bones.size(); i++)
	{
		INode* node = skin.bones[i];
		Matrix3 mat;
		if (SKIN_INVALID_NODE_PTR == i_skin->GetBoneInitTM( node, mat ))
		{
			if (SKIN_INVALID_NODE_PTR == i_skin->GetSkinInitTM( node, mat ))
			{
				mat.IdentityMatrix();
			}
		}
		skin.transforms[i] = Inverse(mat);
	}

	// there is a 75 bone limit for each skinned object.
	if(skin.bones.size()>75)
	{
		G3DAssert("There are more %d bones in the skin(%s).",skin.bones.size(), i_node->GetName());
		return;
	}

	// reset the skin vertex position
	for(int i = 0; i < skin.vertexes.size(); i++)
	{
		VPTNIS& v0 = skin.vertexes[i];
		VPIW& v1 = skin.weights[v0.index];
		v0.pos = v1.pos;
	}

	// build the normal space
	BuildNormal(skin);

	// calculate the bounding box	
	skin.box.Init();
	for(int i = 0; i < skin.vertexes.size(); i++)
	{
		Point3 pt = node_matrix * skin.vertexes[i].pos;
		skin.box += pt;
	}

	// add the skin to the table
	mSkins.push_back(skin);
}
示例#21
0
文件: evalcol.cpp 项目: 2asoft/xray
// Returns the point to be shaded in object coordinates.
Point3 SContext::PObj(void)
{
	return Inverse(tmAfterWSM) * P();
}
示例#22
0
// Returns the point to be shaded in object coordinates.
Point3 SContext::PObj(void)
{
	SCDebugPrint("SContext::PObj\n");
	Matrix3 camToObj = Inverse(pInst->objToWorld * renderer->view.affineTM);
	return camToObj * P();
}
示例#23
0
int EditPatchMod::DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPatch, bool & canUndo) 
{
	ModContextList mcList;	
	INodeTab nodes;	

	if (!ip)
		return 0;

	ip->GetModContexts(mcList, nodes);

	if (mcList.Count() != 1)
	{
		nodes.DisposeTemporary();
		return 0;
	}

	EditPatchData *patchData =(EditPatchData*)mcList[0]->localData;
	if (!patchData)
	{
		nodes.DisposeTemporary();
		return 0;
	}

	// If the mesh isn't yet cached, this will cause it to get cached.
	RPatchMesh *rpatch;
	PatchMesh *patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch);
	if (!patch)
	{
		nodes.DisposeTemporary();
		return 0;
	}
	patchData->RecordTopologyTags(patch);
	RecordTopologyTags();
	patchData->BeginEdit(ip->GetTime());

	// Transform the shape for attachment:
	// If reorienting, just translate to align pivots
	// Otherwise, transform to match our transform
	Matrix3 attMat(1);
	if (attachReorient)
	{
		Matrix3 thisTM = nodes[0]->GetNodeTM(ip->GetTime());
		Matrix3 thisOTMBWSM = nodes[0]->GetObjTMBeforeWSM(ip->GetTime());
		Matrix3 thisPivTM = thisTM * Inverse(thisOTMBWSM);
		Matrix3 otherTM = node->GetNodeTM(ip->GetTime());
		Matrix3 otherOTMBWSM = node->GetObjTMBeforeWSM(ip->GetTime());
		Matrix3 otherPivTM = otherTM * Inverse(otherOTMBWSM);
		Point3 otherObjOffset = node->GetObjOffsetPos();
		attMat = Inverse(otherPivTM) * thisPivTM;
	}
	else 
	{
		attMat = node->GetObjectTM(ip->GetTime()) *
			Inverse(nodes[0]->GetObjectTM(ip->GetTime()));
	}

	// RB 3-17-96 : Check for mirroring
	AffineParts parts;
	decomp_affine(attMat, &parts);
	if (parts.f < 0.0f)
	{
		int v[8], ct, ct2, j;
		int tvInteriors[4], tvHandles[8];
		Point3 p[9];
		
		for (int i = 0; i < attPatch->numPatches; i++)
		{

			// Re-order rpatch
			if (attPatch->patches[i].type == PATCH_QUAD)
			{
				UI_PATCH rpatch=rattPatch->getUIPatch (i);
				int ctU=rpatch.NbTilesU<<1;
				int ctV=rpatch.NbTilesV<<1;
				int nU;
				for (nU=0; nU<ctU; nU++)
				{
					for (int nV=0; nV<ctV; nV++)
					{
						rattPatch->getUIPatch (i).getTileDesc (nU+nV*ctU)=rpatch.getTileDesc (ctU-1-nU+(ctV-1-nV)*ctU);
					}
				}
				for (nU=0; nU<ctU+1; nU++)
				{
					for (int nV=0; nV<ctV+1; nV++)
					{
						rattPatch->getUIPatch (i).setColor (nU+nV*(ctU+1), rpatch.getColor (ctU-nU+(ctV-nV)*ctU));
					}
				}
			}

			// Re-order vertices
			ct = attPatch->patches[i].type == PATCH_QUAD ? 4 : 3;
			for (j = 0; j < ct; j++)
			{
				v[j] = attPatch->patches[i].v[j];
			}
			for (j = 0; j < ct; j++)
			{
				attPatch->patches[i].v[j] = v[ct - j - 1];
			}
			
			// Re-order vecs
			ct  = attPatch->patches[i].type == PATCH_QUAD ? 8 : 6;
			ct2 = attPatch->patches[i].type == PATCH_QUAD ? 5 : 3;
			for (j = 0; j < ct; j++)
			{
				v[j] = attPatch->patches[i].vec[j];
			}
			for (j = 0; j < ct; j++, ct2--)
			{
				if (ct2 < 0)
					ct2 = ct - 1;
				attPatch->patches[i].vec[j] = v[ct2];
			}
			
			// Re-order enteriors
			if (attPatch->patches[i].type == PATCH_QUAD)
			{
				ct = 4;
				for (j = 0; j < ct; j++)
				{
					v[j] = attPatch->patches[i].interior[j];
				}
				for (j = 0; j < ct; j++)
				{
					attPatch->patches[i].interior[j] = v[ct - j - 1];
				}
			}
			
			// Re-order aux
			if (attPatch->patches[i].type == PATCH_TRI)
			{
				ct = 9;
				for (j = 0; j < ct; j++)
				{
					p[j] = attPatch->patches[i].aux[j];
				}
				for (j = 0; j < ct; j++)
				{
					attPatch->patches[i].aux[j] = p[ct - j - 1];
				}
			}
			
#if (MAX_RELEASE < 4000) /* #if (MAX_RELEASE < 4000) */
			// Re-order TV faces if present
			for (int chan = 0; chan < patch->getNumMaps(); ++chan)
			{
				if (attPatch->tvPatches[chan])
				{
					ct = 4;
					for (j = 0; j < ct; j++)
					{
						v[j] = attPatch->tvPatches[chan][i].tv[j];
					}
					for (j = 0; j < ct; j++)
					{
						attPatch->tvPatches[chan][i].tv[j] = v[ct - j - 1];
					}
				}
			}
#else /* #if (MAX_RELEASE < 4000) #else */
			// Re-order TV faces if present
			for(int chan = -NUM_HIDDENMAPS; chan < patch->getNumMaps(); ++chan) 
			{
				if (chan < attPatch->getNumMaps() && attPatch->mapPatches(chan)) 
				{
					ct = attPatch->patches[i].type==PATCH_QUAD ? 4 : 3;
					for (j=0; j<ct; j++) 
					{
						v[j] = attPatch->mapPatches(chan)[i].tv[j];
						tvInteriors[j] = attPatch->mapPatches(chan)[i].interiors[j];
						int a;
						int b;
						a = j*2-1;
						b = j*2;
						if (a<0) a = ct*2-1;
						tvHandles[j*2] = attPatch->mapPatches(chan)[i].handles[a];
						tvHandles[j*2+1] = attPatch->mapPatches(chan)[i].handles[b];
					}
					for (j=0; j<ct; j++) 
					{
						attPatch->mapPatches(chan)[i].tv[j] = v[ct-j-1];
						attPatch->mapPatches(chan)[i].interiors[j] = tvInteriors[(ct)-(j)-1];
						int index = ct-j-1;
						int a;
						int b;
						a = j*2-1;
						b = j*2;
						if (a<0) a = ct*2-1;
						attPatch->mapPatches(chan)[i].handles[b] = tvHandles[index*2];
						attPatch->mapPatches(chan)[i].handles[a] = tvHandles[index*2+1];
					}
				}
			}
#endif /* #if (MAX_RELEASE < 4000) #else #endif */
		}
	}

	int i;
	for (i = 0; i < attPatch->numVerts; ++i)
		attPatch->verts[i].p = attPatch->verts[i].p * attMat;
	for (i = 0; i < attPatch->numVecs; ++i)
		attPatch->vecs[i].p = attPatch->vecs[i].p * attMat;
	attPatch->computeInteriors();

	theHold.Begin();

	// Combine the materials of the two nodes.
	int mat2Offset = 0;
	Mtl *m1 = nodes[0]->GetMtl();
	Mtl *m2 = node->GetMtl();
	bool condenseMe = FALSE;
	if (m1 && m2 &&(m1 != m2))
	{
		if (attachMat == ATTACHMAT_IDTOMAT)
		{
			int ct = 1;
			if (m1->IsMultiMtl())
				ct = m1->NumSubMtls();
			for (int i = 0; i < patch->numPatches; ++i)
			{
				int mtid = patch->getPatchMtlIndex(i);
				if (mtid >= ct)
					patch->setPatchMtlIndex(i, mtid % ct);
			}
			FitPatchIDsToMaterial(*attPatch, m2);
			if (condenseMat)
				condenseMe = TRUE;
		}
		// the theHold calls here were a vain attempt to make this all undoable.
		// This should be revisited in the future so we don't have to use the SYSSET_CLEAR_UNDO.
		theHold.Suspend();
		if (attachMat == ATTACHMAT_MATTOID)
		{
			m1 = FitMaterialToPatchIDs(*patch, m1);
			m2 = FitMaterialToPatchIDs(*attPatch, m2);
		}
		
		Mtl *multi = CombineMaterials(m1, m2, mat2Offset);
		if (attachMat == ATTACHMAT_NEITHER)
			mat2Offset = 0;
		theHold.Resume();
		// We can't be in face subobject mode, else we screw up the materials:
		DWORD oldSL = patch->selLevel;
		DWORD roldSL = patch->selLevel;
		patch->selLevel = PATCH_OBJECT;
		rpatch->SetSelLevel (EP_OBJECT);
		nodes[0]->SetMtl(multi);
		patch->selLevel = oldSL;
		rpatch->SetSelLevel (roldSL);
		m1 = multi;
		canUndo = FALSE;	// Absolutely cannot undo material combinations.
	}
	if (!m1 && m2)
	{
		// We can't be in face subobject mode, else we screw up the materials:
		DWORD oldSL = patch->selLevel;
		DWORD roldSL = rpatch->GetSelLevel();
		patch->selLevel = PATCH_OBJECT;
		rpatch->SetSelLevel (EP_OBJECT);
		nodes[0]->SetMtl(m2);
		patch->selLevel = oldSL;
		rpatch->SetSelLevel (roldSL);
		m1 = m2;
	}

	// Start a restore object...
	if (theHold.Holding())
		theHold.Put(new PatchRestore(patchData, this, patch, rpatch, "DoAttach"));

	// Do the attach
	patch->Attach(attPatch, mat2Offset);
	rpatch->Attach(rattPatch, *patch);
	patchData->UpdateChanges(patch, rpatch);
	patchData->TempData(this)->Invalidate(PART_TOPO | PART_GEOM);

	// Get rid of the original node
	ip->DeleteNode(node);

	ResolveTopoChanges();
	theHold.Accept(GetString(IDS_TH_ATTACH));

	if (m1 && condenseMe)
	{
		// Following clears undo stack.
		patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch);
		m1 = CondenseMatAssignments(*patch, m1);
	}

	nodes.DisposeTemporary();
	ClearPatchDataFlag(mcList, EPD_BEENDONE);
	NotifyDependents(FOREVER, PART_TOPO | PART_GEOM, REFMSG_CHANGE);
	ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL);
	return 1;
}
示例#24
0
bool TransformedPrimitive::IntersectP(const Ray &r) const {
    Transform InterpolatedPrimToWorld;
    PrimitiveToWorld.Interpolate(r.time, &InterpolatedPrimToWorld);
    Transform InterpolatedWorldToPrim = Inverse(InterpolatedPrimToWorld);
    return primitive->IntersectP(InterpolatedWorldToPrim(r));
}
示例#25
0
TArray<FArrangedWidget> FHittestGrid::GetBubblePath( FVector2D DesktopSpaceCoordinate, bool bIgnoreEnabledStatus )
{
	if (WidgetsCachedThisFrame->Num() > 0 && Cells.Num() > 0)
	{
		const FVector2D CursorPositionInGrid = DesktopSpaceCoordinate - GridOrigin;
		const FIntPoint CellCoordinate = FIntPoint(
			FMath::Min( FMath::Max(FMath::FloorToInt(CursorPositionInGrid.X / CellSize.X), 0), NumCells.X-1),
			FMath::Min( FMath::Max(FMath::FloorToInt(CursorPositionInGrid.Y / CellSize.Y), 0), NumCells.Y-1 ) );
		
		static FVector2D LastCoordinate = FVector2D::ZeroVector;
		if ( LastCoordinate != CursorPositionInGrid )
		{
			LastCoordinate = CursorPositionInGrid;
		}

		checkf( (CellCoordinate.Y*NumCells.X + CellCoordinate.X) < Cells.Num(), TEXT("Index out of range, CellCoordinate is: %d %d CursorPosition is: %f %f"), CellCoordinate.X, CellCoordinate.Y, CursorPositionInGrid.X, CursorPositionInGrid.Y );

		const TArray<int32>& IndexesInCell = CellAt( CellCoordinate.X, CellCoordinate.Y ).CachedWidgetIndexes;
		int32 HitWidgetIndex = INDEX_NONE;
	
		// Consider front-most widgets first for hittesting.
		for ( int32 i = IndexesInCell.Num()-1; i>=0 && HitWidgetIndex==INDEX_NONE; --i )
		{
			check( IndexesInCell[i] < WidgetsCachedThisFrame->Num() ); 

			const FCachedWidget& TestCandidate = (*WidgetsCachedThisFrame)[IndexesInCell[i]];

			// Compute the render space clipping rect (FGeometry exposes a layout space clipping rect).
			FSlateRotatedRect DesktopOrientedClipRect = 
				TransformRect(
					Concatenate(
						Inverse(TestCandidate.CachedGeometry.GetAccumulatedLayoutTransform()), 
						TestCandidate.CachedGeometry.GetAccumulatedRenderTransform()
					), 
					FSlateRotatedRect(TestCandidate.CachedGeometry.GetClippingRect().IntersectionWith(TestCandidate.ClippingRect))
				);

			if (DesktopOrientedClipRect.IsUnderLocation(DesktopSpaceCoordinate) && TestCandidate.WidgetPtr.IsValid())
			{
				HitWidgetIndex = IndexesInCell[i];
			}
		}

		if (HitWidgetIndex != INDEX_NONE)
		{
			TArray<FArrangedWidget> BubblePath;
			int32 CurWidgetIndex=HitWidgetIndex;
			bool bPathUninterrupted = false;
			do
			{
				check( CurWidgetIndex < WidgetsCachedThisFrame->Num() );
				const FCachedWidget& CurCachedWidget = (*WidgetsCachedThisFrame)[CurWidgetIndex];
				const TSharedPtr<SWidget> CachedWidgetPtr = CurCachedWidget.WidgetPtr.Pin();
				
				bPathUninterrupted = CachedWidgetPtr.IsValid();
				if (bPathUninterrupted)
				{
					BubblePath.Insert(FArrangedWidget(CachedWidgetPtr.ToSharedRef(), CurCachedWidget.CachedGeometry), 0);
					CurWidgetIndex = CurCachedWidget.ParentIndex;
				}
			}
			while (CurWidgetIndex != INDEX_NONE && bPathUninterrupted);
			
			if (!bPathUninterrupted)
			{
				// A widget in the path to the root has been removed, so anything
				// we thought we had hittest is no longer actually there.
				// Pretend we didn't hit anything.
				BubblePath = TArray<FArrangedWidget>();
			}

			// Disabling a widget disables all of its logical children
			// This effect is achieved by truncating the path to the
			// root-most enabled widget.
			if ( !bIgnoreEnabledStatus )
			{
				const int32 DisabledWidgetIndex = BubblePath.IndexOfByPredicate( []( const FArrangedWidget& SomeWidget ){ return !SomeWidget.Widget->IsEnabled( ); } );
				if (DisabledWidgetIndex != INDEX_NONE)
				{
					BubblePath.RemoveAt( DisabledWidgetIndex, BubblePath.Num() - DisabledWidgetIndex );
				}
			}
			
			return BubblePath;
		}
		else
		{
			return TArray<FArrangedWidget>();
		}
	}
	else
	{
		return TArray<FArrangedWidget>();
	}
}
Matrix3 plMaxNodeBase::GetParentToLocal(TimeValue t)
{
    Matrix3 loc2Par = GetLocalToParent(t);
    Matrix3 par2Loc = Inverse(loc2Par);
    return par2Loc;
}
示例#27
0
int32 SSlider::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const
{
	// we draw the slider like a horizontal slider regardless of the orientation, and apply a render transform to make it display correctly.
	// However, the AllottedGeometry is computed as it will be rendered, so we have to use the "horizontal orientation" when doing drawing computations.
	const float AllottedWidth = Orientation == Orient_Horizontal ? AllottedGeometry.GetLocalSize().X : AllottedGeometry.GetLocalSize().Y;
	const float AllottedHeight = Orientation == Orient_Horizontal ? AllottedGeometry.GetLocalSize().Y : AllottedGeometry.GetLocalSize().X;

	float HandleRotation;
	FVector2D HandleTopLeftPoint;
	FVector2D SliderStartPoint;
	FVector2D SliderEndPoint;

	// calculate slider geometry as if it's a horizontal slider (we'll rotate it later if it's vertical)
	const FVector2D HandleSize = Style->NormalThumbImage.ImageSize;
	const FVector2D HalfHandleSize = 0.5f * HandleSize;
	const float Indentation = IndentHandle.Get() ? HandleSize.X : 0.0f;

	const float SliderLength = AllottedWidth - Indentation;
	const float SliderPercent = ValueAttribute.Get();
	const float SliderHandleOffset = SliderPercent * SliderLength;
	const float SliderY = 0.5f * AllottedHeight;

	HandleRotation = 0.0f;
	HandleTopLeftPoint = FVector2D(SliderHandleOffset - ( HandleSize.X * SliderPercent ) + 0.5f * Indentation, SliderY - HalfHandleSize.Y);

	SliderStartPoint = FVector2D(HalfHandleSize.X, SliderY);
	SliderEndPoint = FVector2D(AllottedWidth - HalfHandleSize.X, SliderY);

	FSlateRect RotatedClippingRect = MyClippingRect;
	FGeometry SliderGeometry = AllottedGeometry;
	
	// rotate the slider 90deg if it's vertical. The 0 side goes on the bottom, the 1 side on the top.
	if (Orientation == Orient_Vertical)
	{
		// Do this by translating along -X by the width of the geometry, then rotating 90 degreess CCW (left-hand coords)
		FSlateRenderTransform SlateRenderTransform = TransformCast<FSlateRenderTransform>(Concatenate(Inverse(FVector2D(AllottedWidth, 0)), FQuat2D(FMath::DegreesToRadians(-90.0f))));
		// create a child geometry matching this one, but with the render transform.
		SliderGeometry = AllottedGeometry.MakeChild(
			FVector2D(AllottedWidth, AllottedHeight), 
			FSlateLayoutTransform(), 
			SlateRenderTransform, FVector2D::ZeroVector);
		// The clipping rect is already given properly in window space. But we do not support layout rotations, so our local space rendering cannot
		// get the clipping rect into local space properly for the local space clipping we do in the shader.
		// Thus, we transform the clip coords into local space manually, UNDO the render transform so it will clip properly,
		// and then bring the clip coords back into window space where DrawElements expect them.
		RotatedClippingRect = TransformRect(
			Concatenate(
				Inverse(SliderGeometry.GetAccumulatedLayoutTransform()), 
				Inverse(SlateRenderTransform),
				SliderGeometry.GetAccumulatedLayoutTransform()), 
			MyClippingRect);
	}

	const bool bEnabled = ShouldBeEnabled(bParentEnabled);
	const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;

	// draw slider bar
	auto BarTopLeft = FVector2D(SliderStartPoint.X, SliderStartPoint.Y - Style->BarThickness * 0.5f);
	auto BarSize = FVector2D(SliderEndPoint.X - SliderStartPoint.X, Style->BarThickness);
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		LayerId,
		SliderGeometry.ToPaintGeometry(BarTopLeft, BarSize),
		LockedAttribute.Get() ? &Style->DisabledBarImage : &Style->NormalBarImage,
		RotatedClippingRect,
		DrawEffects,
		SliderBarColor.Get().GetColor(InWidgetStyle) * InWidgetStyle.GetColorAndOpacityTint()
		);

	++LayerId;

	// draw slider thumb
	FSlateDrawElement::MakeBox( 
		OutDrawElements,
		LayerId,
		SliderGeometry.ToPaintGeometry(HandleTopLeftPoint, Style->NormalThumbImage.ImageSize),
		LockedAttribute.Get() ? &Style->DisabledThumbImage : &Style->NormalThumbImage,
		RotatedClippingRect,
		DrawEffects,
		SliderHandleColor.Get().GetColor(InWidgetStyle) * InWidgetStyle.GetColorAndOpacityTint()
	);

	return LayerId;
}
Matrix3 plMaxNodeBase::GetWorldToLocal(TimeValue t)
{
    Matrix3 l2w = GetLocalToWorld(t);
    Matrix3 w2l = Inverse(l2w);
    return w2l;
}
示例#29
0
void UnwrapMod::ApplyGizmo()
{

	if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) ||
		(fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == CYLINDRICALMAP))
	{
		ApplyGizmoPrivate();
	}
	else
	{
  		theHold.Begin();
		//compute the center
			//get our normal list
		for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
		{
			MeshTopoData *ld = mMeshTopoData[ldID];
			ld->HoldFaceSel();
		}

		for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
		{
			MeshTopoData *ld = mMeshTopoData[ldID];
			ld->HoldFaceSel();

			Tab<Point3> fnorms;
			fnorms.SetCount(ld->GetNumberFaces());
			for (int k=0; k< fnorms.Count(); k++) 
				fnorms[k] = Point3(0.0f,0.0f,0.0f);
				
			//get our projection normal
			Point3 projectionNorm(0.0f,0.0f,0.0f);

			//build normals
			for (int k = 0; k < fnorms.Count(); k++) 
			{
				if (ld->GetFaceSelected(k))
				{
							// Grap the three points, xformed
					int pcount = 3;
					//				if (gfaces[k].flags & FLAG_QUAD) pcount = 4;
					pcount = ld->GetFaceDegree(k);//gfaces[k]->count;

					Point3 temp_point[4];
					for (int j=0; j<pcount; j++) 
					{
						int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j];							
						if (j < 4)
							temp_point[j] = ld->GetGeomVert(index);//gverts.d[index].p;
					}
					
					fnorms[k] = Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]);
				}
			}
				
			BitArray front,back,left,right,top,bottom;
			front.SetSize(ld->GetNumberFaces());
			front.ClearAll();
			back = front;
			left = front;
			right = front;
			top = front;
			bottom = front;

			Tab<Point3> norms;

			Matrix3 gtm(1);
			TimeValue t = 0;
			if (ip) t = ip->GetTime();
			if (tmControl)
				tmControl->GetValue(t,&gtm,FOREVER,CTRL_RELATIVE);

			norms.SetCount(6);
			for (int i = 0; i < 3; i++)
			{
				Point3 v = gtm.GetRow(i);
				norms[i*2] = Normalize(v);
				norms[i*2+1] = norms[i*2] * -1.0f;
			}
				
			for (int k=0; k< ld->GetNumberFaces(); k++) 
			{
				if (ld->GetFaceSelected(k))
				{
					int closestFace = -1;
					float closestAngle = -10.0f;
					for (int j = 0; j < 6; j++)
					{
						float dot = DotProd(norms[j],fnorms[k]);
						if (dot > closestAngle)
						{
							closestAngle = dot;
							closestFace = j;
						}
					}
					if (closestFace == 0)
						front.Set(k,TRUE);
					else if (closestFace == 1)
						back.Set(k,TRUE);
					else if (closestFace == 2)
						left.Set(k,TRUE);
					else if (closestFace == 3)
						right.Set(k,TRUE);
					else if (closestFace == 4)
						top.Set(k,TRUE);
					else if (closestFace == 5)
						bottom.Set(k,TRUE);
				}
			}


			gtm.IdentityMatrix();
			if (tmControl)
				tmControl->GetValue(t,&gtm,FOREVER,CTRL_RELATIVE);

			Point3 xvec,yvec,zvec;
			xvec = gtm.GetRow(0);
			yvec = gtm.GetRow(1);
			zvec = gtm.GetRow(2);
  			Point3 center = gtm.GetRow(3);


			for (int k = 0; k < 6; k++)
			{

				Matrix3 tm(1);
				if (k == 0)
				{
					tm.SetRow(0,yvec);
					tm.SetRow(1,zvec);
					tm.SetRow(2,xvec);
					ld->SetFaceSelection(front);
				}
				else if (k == 1)
				{
					tm.SetRow(0,yvec);
					tm.SetRow(1,zvec);
					tm.SetRow(2,(xvec*-1.0f));

					ld->SetFaceSelection(back);
				}
				else if (k == 2)
				{
					tm.SetRow(0,xvec);
					tm.SetRow(1,zvec);
					tm.SetRow(2,yvec);

					ld->SetFaceSelection(left);
				}
				else if (k == 3)
				{
					tm.SetRow(0,xvec);
					tm.SetRow(1,zvec);
					tm.SetRow(2,(yvec *-1.0f));

					ld->SetFaceSelection(right);
				}
				else if (k == 4)
				{
					tm.SetRow(0,xvec);
					tm.SetRow(1,yvec);
					tm.SetRow(2,zvec);

					ld->SetFaceSelection(top);
				}
				else if (k == 5)
				{
					tm.SetRow(0,xvec);
					tm.SetRow(1,yvec);
					tm.SetRow(2,(zvec*-1.0f));

					ld->SetFaceSelection(bottom);
				}

				

				tm.SetRow(3,center);

				if (!fnGetNormalizeMap())
				{
					for (int i = 0; i < 3; i++)
					{
						Point3 vec = tm.GetRow(i);
						vec = Normalize(vec);
						tm.SetRow(i,vec);
					}
				}

				tm = mMeshTopoData.GetNodeTM(t,ldID) * Inverse(tm);
				ld->ApplyMap(fnGetMapMode(), fnGetNormalizeMap(), tm, this);				
			}
			ld->RestoreFaceSel();
		}

		theHold.Accept(GetString(IDS_PW_PLANARMAP));
		
	}

}
示例#30
0
template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
{
	// make copy of a in case Inverse() overwrites it
	Element a1(a);
	return Add(a1, Inverse(b));
}