Question about Timer

Apprentice
Posts: 9
Joined: 2010.02
Post: #1
Hi, i'am working on a Editor, and i like to move all Objects Timebased, here a snippet of my code:
Code:
/* Create an update timer */
    timer = [NSTimer scheduledTimerWithTimeInterval: (0.001f) target: self
                                           selector: @selector(heartbeat) userInfo: nil
                                            repeats: YES];


- (void) drawRect: (NSRect) rect
{        
    start = [NSDate timeIntervalSinceReferenceDate];
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glLoadIdentity();
    
    [_camera animate:deltaTime];
    
    glFlush();                                            
    [[self openGLContext] flushBuffer];    
    
    end = [NSDate timeIntervalSinceReferenceDate];
    deltaTime = end-start;
}

move my objects:
Code:
object.position+=velocity*deltaTime;

Is this the right way??
Quote this message in a reply
Member
Posts: 100
Joined: 2006.05
Post: #2
Your move objects code is correct, but I didn't think you could just subtract pointer values like that. I believe you can cut some overhead by just doing this:

Code:
NSDate *clockTime = [[[NSDate alloc] initWithTimeIntervalSinceNow:0] retain];
double last = (double)[clockTime timeIntervalSinceNow];

void renderCode {
    deltaT = (double)[clockTime timeIntervalSinceNow] - (double)last;
    last = (double)[clockTime timeIntervalSinceNow];
}

or something similar suiting your needs. I'm also assuming you have some kind of setNeedsDisplay or display call somewhere in the heartbeat selector.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
They're NSTimeIntervals, not pointers.

Also, you definitely don't want to create an NSDate object like that, and if you did, you definitely wouldn't want to overretain it Rasp

I haven't thought whether the OP's code is OK or not, but yours is definitely not good Rasp
Quote this message in a reply
Member
Posts: 100
Joined: 2006.05
Post: #4
Bleh, I thought he was saying:

start = [NSDate dateWithIntervalSinceReferenceDate];

Wacko Ignore me... That's what happens when you read too quickly (especially at 6:00AM).

Anyway, what's wrong with having one static NSDate object? Does alloc:init automatically retain? I know if I use a convenience method the runtime complains because there is no auto-release pool available during static initialization. I sidestepped all of this and and just made a Clock class (more portable).
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #5
That's one way to do it. Here's an article that demonstrates another way, and points out a few pitfalls of the variable interval approach: http://www.sacredsoftware.net/tutorials/...tion.xhtml
Quote this message in a reply
Member
Posts: 100
Joined: 2006.05
Post: #6
Oh, I see the problem now. Your deltaTime is only measuring how long it takes for you to render, not how long it has been since render was called (what you want). Rearrange it as follows:

Code:
start = [NSDate timeIntervalSinceReferenceDate];
deltaTime = end-start;
end = start;

animate(deltaTime);

deltaTime is computed before end is set so it will be using the end set in the previous loop. You'll want to make sure that end is initialized to some value close (preferably equal to) start the first time around or you'll be sending an invalid deltaTime to your animate routine (which could throw your animations into an unexpected state before anything even starts).
Quote this message in a reply
Apprentice
Posts: 9
Joined: 2010.02
Post: #7
Nevada Wrote:Oh, I see the problem now. Your deltaTime is only measuring how long it takes for you to render, not how long it has been since render was called (what you want). Rearrange it as follows:

Code:
start = [NSDate timeIntervalSinceReferenceDate];
deltaTime = end-start;
end = start;

animate(deltaTime);

deltaTime is computed before end is set so it will be using the end set in the previous loop. You'll want to make sure that end is initialized to some value close (preferably equal to) start the first time around or you'll be sending an invalid deltaTime to your animate routine (which could throw your animations into an unexpected state before anything even starts).

Ah, thanks thats what i'am looking for ;-).

one more question :-)
i'am working on a simple particlesystem, in this i like to fade particle over a time here a snippet:
Code:
-(void)initParticles:(int)i
{
    float theta = (float) ((rand() % 360) - 180) * 180 / PI;
    
    p[i].velocity.x = _velocity.x+ (cos(theta)*1.5f);
    p[i].velocity.y = _velocity.y+ ((float)(rand() % 4095) * 0.000025f * _velocity.y);
    p[i].velocity.z = _velocity.z+ (sin(theta)*1.5f);
    
    p[i].gravity = _gravity;
    p[i].position = _position;
    p[i].lifeTime = getRandomMinMax(1.0f,_lifeTime);
    p[i].timeAlive = 0.0f;
    p[i].size = _size;
    p[i].color = _pvRandomIVector(makeVector(0.0f, 0.0f, 0.0f), makeVector(1.0f, 1.0f, 1.0f) );
}

-(void)update:(float)timeDelta
{
    int i;
    
    for (i=0; i<NUMPARTICLES; i++)
    {
        p[i].timeAlive+=timeDelta;
        
        p[i].velocity.x += p[i].gravity.x*timeDelta;
        p[i].velocity.y += p[i].gravity.y*timeDelta;
        p[i].velocity.z += p[i].gravity.z*timeDelta;
            
        p[i].position.x+=p[i].velocity.x*timeDelta;
        p[i].position.y+=p[i].velocity.y*timeDelta;
        p[i].position.z+=p[i].velocity.z*timeDelta;
            
        if (p[i].position.y < 0.0f)
            p[i].velocity.y = -0.6 * p[i].velocity.y + ((rand() % 255) / 255.0f);

        if(p[i].timeAlive >= p[i].lifeTime)
        {
            [self initParticles:i];
        }
    }
}

-(void)render
{
    glBindTexture(GL_TEXTURE_2D, _texture);
    
    glEnable(GL_BLEND);            
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    
    glEnable(GL_POINT_SPRITE);
    glPointSize( _size);
    glBegin(GL_POINTS);
    
    int i;
    for (i=0; i<NUMPARTICLES; i++)
    {        
        glVertex3f(p[i].position.x, p[i].position.y, p[i].position.z);
        glColor4d(p[i].color.x, p[i].color.y, p[i].color.z, 1- (p[i].timeAlive / p[i].lifeTime) );
    }
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_POINT_SPRITE);
}
the problem is, some particle don't fade as expected, the are blinking and change the color since they are fade out. (difficult to explain, sorry for my bad english).
i cant find whats going wrong here.
when i using only one particle the system works as expected, more than one the system sucks, anyone know whats wrong??

thanks
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #8
Not sure if it's your only problem, but if you want that call to glColor4d to affect the current particle you're drawing instead of the next one, you'll want to put it before the glVertex3f call.
Quote this message in a reply
Apprentice
Posts: 9
Joined: 2010.02
Post: #9
ThemsAllTook Wrote:Not sure if it's your only problem, but if you want that call to glColor4d to affect the current particle you're drawing instead of the next one, you'll want to put it before the glVertex3f call.

damn Mad its so simple, thank you.
what you mean, with "only problem", you see more ???
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #10
All I mean is that I was only skimming, so although that was the only problem I noticed, I might have found more if I read the code more closely. Since it fixed your bug, though, maybe I wouldn't. Smile
Quote this message in a reply
Post Reply