Announcement

Collapse
No announcement yet.

VRayMesh

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • VRayMesh

    Hey everyone,

    I was wondering if anyone had any insight in the exact calculations done within VRayMeshes to calculate the time based on the settings provided, eg. animOffset, animSpeed, animType.
    I'm compiling the Maya's gpuCache plug-in with time offsets and would love the attributes to trigger the exact same time as the VRayMeshes.
    This way we can animate the super-fast gpuCaches and render the VRayMeshes with the same settings.

    Code:
    if (fCacheAnimType == 0) // Loop
    	{
    		// the animation is looped by skipping to the first frame once it has finished
    		double t = (double)(MAnimControl::currentTime().as(MTime::kSeconds) * fCacheAnimSpeed) + fCacheAnimOffset;
    		return fmod(t, fCacheAnimEndTime - fCacheAnimStartTime) + fCacheAnimStartTime;
    	}
    	else if (fCacheAnimType == 1) // Play Once
    	{
    		// the animation is played once;
    		return (double)(MAnimControl::currentTime().as(MTime::kSeconds) * fCacheAnimSpeed) + fCacheAnimOffset;
    	}
    	else if (fCacheAnimType == 2) // Ping-Pong
    	{
    		// The animation is looped by playing it backwards once the last frame 
    		// has been reached and then playing it forward again when the first frame is reached
    		// Reference: http://stackoverflow.com/questions/11543685/oscillate-or-ping-pong-between-two-values
    
    		double t = (double)(MAnimControl::currentTime().as(MTime::kSeconds) * fCacheAnimSpeed) + fCacheAnimOffset;
    
    		double range = fCacheAnimEndTime-fCacheAnimStartTime;
    		double cycle_length = range*2;
    		double state = fmod(t-fCacheAnimStartTime, cycle_length);
    
    		if (state > range)
    			state = cycle_length-state;
    
    		return state + fCacheAnimStartTime;
    	}
    	else if (fCacheAnimType == 3) 
    	{
    		// Still - the animation is not played. 
    		// Instead just one frame of the animation is shown. 
    		// You can select which that frame is with the help of the Start offset parameter.
    		return fCacheAnimOffset;
    	}
    	else {
    		return 0.0;
    	}
    It's hard to test at the moment because it seems the gpuCache isn't finding the right time range yet, but that's a Maya/Alembic thing I suppose.
    For anyone that knows anything about it I'm using this to find the animation range.

    Code:
    // Read time range
    TimeInterval interval(TimeInterval::kInvalid);
    cacheReader->readAnimTimeRange(interval);
    fCacheAnimStartTime = interval.startTime();
    fCacheAnimEndTime = interval.endTime();
    By the way... is it possible to use VRayMesh to run it as fast as gpuCaches?

  • #2
    One of our developers is looking into the possibility to display VRayMesh objects directly on the GPU, like the GPU cache, so this will be done soon.

    As for the time calculations, they happen like this:
    Code:
    double VUtils::calcFrameIndex(double frame, MeshFileAnimType::Enum animType, int animStart, int animLength, double animOffset, double speed) {
    	switch (animType) {
    		default:
    		case MeshFileAnimType::Loop:
    			frame=fmod(animOffset+(frame-animStart)*speed, animLength);
    			if (frame<0)
    				frame+=animLength;
    			frame+=animStart;
    			break;
    		case MeshFileAnimType::Once:
    			frame=clamp<double>(animOffset+(frame-animStart)*speed, 0.0, animLength-1.0)+animStart;
    			break;
    		case MeshFileAnimType::PingPong:
    			frame=fmod(animOffset+(frame-animStart)*speed, animLength*2-2); // subtract 2 to remove the duplicate frames
    			if (frame<0)
    				frame+=2*animLength-2;
    			if (frame>=animLength) {
    				frame=2*animLength-2-frame;
    			}
    			frame+=animStart*speed;
    			break;
    		case MeshFileAnimType::Still:
    			frame=clamp(animOffset+animStart, 0.0, animLength-1.0);
    			break;
    	}
    	return frame;
    }
    
    float GeomMeshFile::getFrameIndex(MeshInterface *mfile, double currentFrame) {
    	int firstFrame=0;
    	int numFrames=0x7FFFFFFF; // Used if the proxy file name contains %d string - we don't know how many frames we have
    	if (mfile) {
    		numFrames=mfile->getNumFrames();
    		if (numFrames<=1) return 0.0f; // The proxy has only one frame, so no animation
    
    		// Otherwise, the proxy has more than one frame, definitely has animation
    		isProxyAnimated=true;
    	} else if (animOverride) {
    		if (animLength<=1) return 0.0f; // The proxy has only one frame, so no animation
    		numFrames=animLength;
    		firstFrame=animStart;
    		isProxyAnimated=true;
    	}
    
    	// Compute the actual frame number
    	double frameIndex=0.0f;
    	frameIndex=VR::calcFrameIndex(currentFrame, static_cast<VR::MeshFileAnimType::Enum>(animType), firstFrame, numFrames, animOffset, animSpeed);
    
    	return (float) frameIndex;
    }
    I see that in your code you are using the time in seconds, but we operate with frames internally.

    Best regards,
    Vlado
    I only act like I know everything, Rogers.

    Comment


    • #3
      Thanks Vlado!

      The gpuCache's readSample() methods are using seconds as time values unfortunately. Only thing I'd need to adapt is the 2 frame offset you're using to subtract (2/FPS) seconds. Just need to figure out whether it uses a constant FPS internally or Maya's currently set units, I'll currently be testing:

      Code:
       double two_frames_in_seconds = MTime(2.0, MTime::uiUnit()).as(MTime::kSeconds);
      Now all I need to get working is having the gpuCache read the length of the animation.
      Somehow it never updates if I put it in the getCachedGeometry() method like so:

      Code:
      cacheReader->readAnimTimeRange(fCacheAnimTimeInterval);
      This gpuCache code is making my head explode.
      Without knowing the length of the cache all that works is offsetting the animations, not the looping/ping-pong.

      Comment


      • #4
        For anyone else jumping into compiling gpuCaches with these time offsets, I acquired the animRange through the SubNode:

        Code:
        	// Get time range of data
            const SubNode::Ptr geom = getCachedGeometry();
            if (!geom) return 0.0;
        
            const SubNodeData::Ptr geomData = geom->getData();
            if (!geomData) return 0.0;
        
        	fCacheAnimTimeInterval = geomData->animTimeRange();
        Now it just seems that over time the animation goes out of sync. So either the animRange includes/excludes the outer bounds (start/end frame) differently than the VRayMesh OR the seconds are interpreted in the wrong format. Knowing Maya it's likely the latter.

        Investigating more!

        Comment


        • #5
          I had some more time debugging the animations going out of sync. It seems that the VRayMesh doesn't skip the last (or first?) frame when on 'loop' even though the documentation states: "Loop - the animation is looped by skipping to the first frame once it has finished". Basically at the end of the animation it repeats the same frame twice. Any idea where that could be coming from?

          The interesting thing is that using the code example above (for calculating the loop based on a frame value) it does skip the frame for my gpuCache?
          Not sure what the intended behavior is for VRayMeshes?

          Comment


          • #6
            Just to answer this for others. The difference between the time offsetted gpuCaches and VRayMeshes with the code provided above was that I didn't take the animLength correctly.
            I did animEnd-animStart but forgot it should've been inclusive frame ranges so this length is missing a single frame. It was a simple as animEnd-animStart+1.

            @Vlado, thanks again for sharing the code. I can now easily retime our heavier scenes with gpuCaches and render as VRayMeshes, sweet stuff!

            Comment


            • #7
              Well, glad to know that it worked Our own code for GPU preview of .vrmesh files seems almost done too.

              Best regards,
              Vlado
              I only act like I know everything, Rogers.

              Comment

              Working...
              X