Author Topic: Billboarded objects scaled double when using scale value in rotation matrix?  (Read 939 times)

Offline sticksen

  • byte
  • *
  • Posts: 15
    • View Profile
Hi,

alright, I guess this is a problem onlz occuring to me, but I just wanted to let you know:

When the scale parts of an Object3D rotation matrix are used (for some cause), billboarded objects seem to be scaled double the size it's supposed to be. Could there be an easy fix (maybe in a new release)?

Cheers,
Marc

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
I'm not sure that the tweaking that you did to the rotation matrix in the other thread is actually needed. I think that the scale2-method in this example is equivalent:

Code: [Select]
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;

public class ScaleTest {

private Object3D rootNode = null;

public static void main(String[] args) {
ScaleTest st = new ScaleTest();
st.doIt();
}

public void doIt() {

init();
scale(1.5f, new SimpleVector(2, 3, 4));
scale(0.1125f, new SimpleVector(12, 5, 11));
scale(10.1125f, new SimpleVector(0, -0.5f, 3));
System.out.println(rootNode.getWorldTransformation());
System.out.println(rootNode.getTranslation());

init();
scale2(1.5f, new SimpleVector(2, 3, 4));
scale2(0.1125f, new SimpleVector(12, 5, 11));
scale2(10.1125f, new SimpleVector(0, -0.5f, 3));
System.out.println(rootNode.getWorldTransformation());
System.out.println(rootNode.getTranslation());
}

public void init() {
rootNode = new Object3D(0);
rootNode.rotateX(2);
rootNode.rotateY(34);
rootNode.rotateZ(1.45f);

rootNode.translate(1, 34, 12.334f);
}

public void scale(float scaleDelta, SimpleVector worldCoord) {
SimpleVector translation = rootNode.getTranslation();
Matrix mat = rootNode.getRotationMatrix();
mat.translate(-(worldCoord.x - translation.x), -(worldCoord.y - translation.y), 0);
Matrix scale = getScaleMatrix(scaleDelta);
mat.matMul(scale);
mat.translate(worldCoord.x - translation.x, worldCoord.y - translation.y, 0);
}

public void scale2(float scaleDelta, SimpleVector worldCoord) {
// This methods splits the translation into translation and origin, to preserve the initial translation just like the scale()-method does it.
// If this is not needed, this splitting isn't needed and one can simply use translate() instead.
SimpleVector translation = rootNode.getTranslation();
SimpleVector origin = rootNode.getOrigin();
rootNode.scale(scaleDelta);
SimpleVector pv = new SimpleVector(worldCoord.x - translation.x - origin.x, worldCoord.y - translation.y - origin.y, 0);
pv.scalarMul(1 - scaleDelta);
pv.add(origin);
rootNode.setOrigin(pv);
}

private Matrix getScaleMatrix(float scale) {
Matrix scaleMat = new Matrix();
scaleMat.setDump(new float[] { scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, 1 });
return scaleMat;
}
}

The scaling for bill boarded objects goes wrong with your tweaked rotation matrix, because it's baked into the matrix and therefor lost when using a bill board. With scale2(), this should't be the case anymore.
« Last Edit: October 26, 2011, 09:43:10 pm by EgonOlsen »

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
Note: I've simplified the call by leaving out whatever getCollisionCoordinates() does and taking the input vector directly...this shouldn't matter for the actual idea IMHO.

Offline sticksen

  • byte
  • *
  • Posts: 15
    • View Profile
Thanks for your help! I have to look into this later, will report here!