Thread: scaling function

  1. #1
    Registered User
    Join Date
    Mar 2003
    Posts
    25

    scaling function

    Hello,

    I am working on a school assignment and have one small problem. Here's the general description of the assignment:

    Create an openGL program (2D) that can be used to be a street map of a given area. So some functions are making buildings and streets, being able to place them and rotate and scale them. Now I've got most of that done already, don't worry, I didn't come here looking for someone to do my homework for me ... I'm just stuck on one thing. The tricky part came with group things together. Everything is a rectangle. I have a WorldObject class which has subclasses for building and street, which is not so relevant anyway. WorldObject has a vector of rectangles in this object.

    So to rotate an object, I need to rotate every rectangle, with respect to the center of the object. After much math on paper and some old trial and error I figured a good way to do this that works great. My problem comes with the scaling function. I've got a function that almost works, but is slightly off, if I have two rectangles right next to each other (touching) and I increment the scale, they'll be slowly moving towards each other instead of the edges staying just next to each other like they should. It's close to perfect, and I may just give up and leave it like this, but I'm really a perfectionist and want this to work properly. So here's where I would be ever so greatful for your help. This is the code I have for this function:

    Code:
    void Rectangle::incrementCenter(Point2D * pointOfOrigin, GLfloat width, GLfloat height) {
    	if (this->center == *pointOfOrigin) return;
    
    	// normalize to origin
    	this->center -= *pointOfOrigin;
    
    	// determine z and add the new distance to it (will usually be 1)
    	double z = sqrt(pow(this->center.x,2) + pow(this->center.y,2));
    
    	double z1 = sqrt(pow(width,2) + pow(height,2));
    
    	if (width < 0 || height < 0 && !(width < 0 && height < 0)) z1 *= -1;
    
    	z += z1;
    
    	// determine angle between center of rectangle and center of the object
    	double rads = atan(this->center.y/this->center.x);
    
    	// see comments in rotateCenter for this one
    	if (this->center.x < 0 && this->center.y > 0 ||
    		this->center.x < 0 && this->center.y < 0) {
    		rads += PI;
    	} 
    	Point2D scaledCenter = Point2D(z*cos(rads), z*sin(rads));
    	this->center = scaledCenter + *pointOfOrigin;
    }
    
    // the above gets called from WorldObject
    
    void WorldObject::scale(GLfloat width, GLfloat height) {
    
    	Point2D * center = calulateCenter();
    
    	// how many rectangles in this object
    	int size = (int) this->rectangles.size();
    
    	for (vector<Rectangle>::iterator it = this->rectangles.begin(); it != this->rectangles.end(); it++) {
    		it->incrementScale(width,height);
    
    		// the center should only move by the width increment/size since there may be multiple
    		// rectangles enlarged
    		// not sure now why I put the 2 there but removing it makes this bad
    		it->incrementCenter(center,width/(2*size),height/(2*size));
    	}
    }
    Sorry if this is the wrong forum, but I figured graphics related would best fit the game programming forum, even if it's not quite a game.

    Thanks for any help on this

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If the four corners of the rectangle are all drawn using offsets on x and y from a central point, scaling them is a matter of a simple multiplication.

    I'm not sure why you are needing the angle here at all in either of these operations. Rotation only requires a radian value to increment/decrement the rotation.

    float fRotX=fOrgX*cos(fAngle)-fOrgY*sin(fAngle);
    float fRotY=fOrgX*sin(fAngle)+fOrgY*cos(fAngle);

    A translate is simple:

    fTransX=fOrgX+fDirectionX*fDistance;
    fTransY=fOrgY+fDirectionY*fDistance;

    These can all be done using matrices.

    I will show the matrices for LEFT HANDED only since that is what I'm used to:

    Rotate Z
    cos(ZAngle),-sin(ZAngle),0,0
    sin(ZAngle),cos(ZAngle),0,0
    0,0,1,0
    0,0,0,1

    Translate dx,dy,dz
    1,0,0,dx
    0,1,0,dy
    0,0,1,dz
    0,0,0,1

    Scale sx,sy,sz
    sx,0,0,0
    0,sy,0,0
    0,0,sz,0
    0,0,0,1

    Transform a vector by a 4x4 matrix - [M]*v
    M00 M01 M02 M03
    M10 M11 M12 M13
    M20 M21 M22 M23
    M30 M31 M32 M33

    fNewX=fOrgX*mat[M00]+fOrgY*mat[M01]*fOrgZ*mat[M02]+mat[M03];
    fNewY=fOrgX*mat[M10]+fOrgY*mat[M11]*fOrgZ*mat[M12]+mat[M13];
    fNewZ=fOrgX*mat[M20]+fOrgY*mat[M21]*fOrgZ*mat[M22]+mat[M23];

    Concatenate 4x4 matrices
    Code:
    void MatMul(float mat1[4][4],float mat2[4][4],float result[4][4])
    {  
      for (int i=0;i<4;i++)
      {
        for (int j=0;j<4;j++)
        {
           result[i][j]=0.0f;
           for (int k=0;k<4;k++)
           {
              mat[i][j]+=mat1[i][k]*mat2[k][j];
           }
        }
      }
    }
    Last edited by VirtualAce; 10-23-2006 at 01:04 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  2. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  3. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  4. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  5. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM