Child translation after remove parent relation

Started by Alexey, April 23, 2011, 04:02:07 PM

Previous topic - Next topic

Alexey

If after parent object rotation remove child, child object reset translation/rotation which were applied by parent relation.
It is a bug? How i can leave child in current place after removing parent relation?

Alexey

How does the process of rotation and translation works for child objects?
Can you tell, please, if i'm going to override child-parent relation, how better implement child rotation near parent pivot?

EgonOlsen

It's not a bug. It's by design. It's not that easy to transfer the transformations of the complete parent-chain to the child. Maybe this thread helps: http://www.jpct.net/forum2/index.php/topic,2011.0.html. Another idea that comes to my mind, is to remove the actual parent, create a dummy object (that doesn't even belong to the world and is empty), set the parent's translation, rotation and rotation pivot to that dummy object and make it a parent of the child object.

Alexey

Unfortunately solution from that thread not approached. In my case, for example -  5 objects

  (obj1)(---obj2---)(obj3)(---obj4---)(obj5)   on some axis

obj3 set parent to others & rotate, than remove all child relation, after that obj1 or another can be parent for same group of objects in another axis etc.
And dummy object solution i think not good for this situation, because possible many relation changes sequences.

For overriding relations i need move child's rotation pivot to parent rotation pivot, i tried use child.rotateAxis(parent.get*Axis(), angle) , but this some reason did not work, maybe need convert parent axis vector?

p.s. when in collision listener i try set texture to collision polygon (texture not set before) happens arrayIndexOutOfBounds, but polygon ID  < maxPolyIds.
p.p.s sorry for my english.



EgonOlsen

Albeit i don't really get what you are after, my gut feeling tells me that you might be better of with doing the transformations yourself instead of relying on the parent/child-relations in this case. Shouldn't be that hard....if i got this correctly, all you have to do is to place the rotation pivot of any object other than obj3 to the distance of this object to obj3 and apply the rotations on each.

About setting the texture: Which version are you using? This used to happen when you tried to change a texture on a stripped object. Newer versions from the "new version"-thread should silently skip this operation in that case. Changing a texture on the fly doesn't really work anyway, because it would require a recompilation of the mesh, which isn't supported. This will work only if the polygon in question already used another texture than all the others, which is unlikely....or if the object hasn't been rendered at all, which isn't the case here. What is supported, is modification of texture coordinates on the fly, if the object is compiled with compile(true, false); and not stripped. With this, you can use one larger texture that consists of multiple smaller ones and switch them by changing the u/v-coordinates.

Alexey

Thanks for reply, in my case pivot move to "parent", then rotate after that i mast return pivot to 0,0,0 but if i return it after call rotations methods pivot changes don't apply and rendering rotation around 0,0,0 ;
I write rotation function, but some strange happens with translation -

Looks like translation vector multiply by 2 after setting rotation matrix: mast be -12.869117 -10.0 -15.309665 1.0 , but - -27.011253 -20.0 -29.451801 1.0
thats code & log of it:


                System.out.println("world matrix = " + getWorldTransformation());
System.out.println("operation matrix = " + m);

Matrix currentTransformMAtrix = getWorldTransformation();
currentTransformMAtrix.matMul(m);
Matrix translateMatrix = new Matrix();
translateMatrix.setRow(3, currentTransformMAtrix.get(3, 0), currentTransformMAtrix.get(3,1), currentTransformMAtrix.get(3, 2), 1);
System.out.println("Result mul matrix = " + currentTransformMAtrix);

setRotationMatrix(currentTransformMAtrix);
System.out.println("world matrix after rotation = " + getWorldTransformation());
setTranslationMatrix(translateMatrix);
System.out.println("world matrix after translation = " + getWorldTransformation());



04-29 08:18:28.314: INFO/System.out(216): world matrix = (
04-29 08:18:28.314: INFO/System.out(216): -3.214496E-8 1.04 3.214496E-8 0.0
04-29 08:18:28.314: INFO/System.out(216): -0.735391 -4.5459842E-8 0.735391 0.0
04-29 08:18:28.314: INFO/System.out(216): 0.735391 0.0 0.735391 0.0
04-29 08:18:28.314: INFO/System.out(216): -14.142136 -10.0 -14.142136 1.0
04-29 08:18:28.314: INFO/System.out(216): )
04-29 08:18:28.314: INFO/System.out(216): operation matrix = (
04-29 08:18:28.324: INFO/System.out(216): 0.99627036 0.0 0.08628637 0.0
04-29 08:18:28.324: INFO/System.out(216): 0.0 1.0 0.0 0.0
04-29 08:18:28.324: INFO/System.out(216): -0.08628637 0.0 0.99627036 0.0
04-29 08:18:28.324: INFO/System.out(216): 0.0 0.0 0.0 1.0
04-29 08:18:28.324: INFO/System.out(216): )
04-29 08:18:28.324: INFO/System.out(216): Result mul matrix = (
04-29 08:18:28.324: INFO/System.out(216): -3.479874E-8 1.04 2.92514E-8 0.0
04-29 08:18:28.324: INFO/System.out(216): -0.79610246 -4.5459842E-8 0.66919404 0.0
04-29 08:18:28.335: INFO/System.out(216): 0.66919404 0.0 0.79610246 0.0
04-29 08:18:28.335: INFO/System.out(216): -12.869117 -10.0 -15.309665 1.0
04-29 08:18:28.335: INFO/System.out(216): )
04-29 08:18:28.335: INFO/System.out(216): world matrix after rotation = (
04-29 08:18:28.335: INFO/System.out(216): -3.479874E-8 1.04 2.92514E-8 0.0
04-29 08:18:28.335: INFO/System.out(216): -0.79610246 -4.5459842E-8 0.66919404 0.0
04-29 08:18:28.335: INFO/System.out(216): 0.66919404 0.0 0.79610246 0.0
04-29 08:18:28.344: INFO/System.out(216): -27.011253 -20.0 -29.451801 1.0
04-29 08:18:28.344: INFO/System.out(216): )
04-29 08:18:28.344: INFO/System.out(216): world matrix after translation = (
04-29 08:18:28.344: INFO/System.out(216): -3.479874E-8 1.04 2.92514E-8 0.0
04-29 08:18:28.354: INFO/System.out(216): -0.79610246 -4.5459842E-8 0.66919404 0.0
04-29 08:18:28.354: INFO/System.out(216): 0.66919404 0.0 0.79610246 0.0
04-29 08:18:28.354: INFO/System.out(216): -25.738234 -20.0 -30.61933 1.0
04-29 08:18:28.354: INFO/System.out(216): )


p.s. why method to set transformation matrix is not present?

Alexey

I see that the setRotationMatrix set translation too.
I solve my issue by this class:


public class Object3dEx extends Object3D {
    private static final short childMax = 10;
    private String group;
    private int childCnt = 0;
    private Object3dEx[] children = new Object3dEx[childMax];

    //Rotation around vector cache
    private Matrix cacheRotAxisMat;
    private float cacheRotAng;
    private float cacheRotAngCos;
    private float cacheRotAngSin;
    private SimpleVector cacheRotVec;


    public Object3dEx(Object3D obj) {
        super(obj, true);
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public void addChildEx(Object3dEx o) {
        if (o != null && childCnt < childMax) {
            children[childCnt] = o;
            ++childCnt;
        }
    }

    public void removeChildEx(Object3dEx o) {
        if (o != null) {
            for (int i = 0; i < children.length; i++) {
                if (o.equals(children[i])) {
                    children[i] = null;
                    --childCnt;
                }
            }
        }
    }

    @Override
    public void translate(float x, float y, float z) {
        translate(new SimpleVector(x, y, z));
    }

    @Override
    public void translate(SimpleVector trans) {
        super.translate(trans);
        if (children != null && children.length > 0) {
            for (Object3dEx ch : children) {
                if (ch != null) {
                    ch.translate(trans);
                }
            }
        }
    }

    @Override
    public void rotateX(float w) {
        super.rotateX(w);
        rotateChildren(w, 0, 0);
    }

    @Override
    public void rotateY(float w) {
        super.rotateY(w);
        rotateChildren(0, w, 0);
    }

    @Override
    public void rotateZ(float w) {
        super.rotateZ(w);
        rotateChildren(0, 0, w);
    }

    @Override
    public void setScale(float absScale) {
        super.setScale(absScale);
        if (children != null && children.length > 0) {
            for (Object3dEx ch : children) {
                if (ch != null) {
                    ch.setScale(absScale);
                }
            }
        }
    }

    @Override
    public void scale(float scale) {
        super.scale(scale);
        if (children != null && children.length > 0) {
            for (Object3dEx ch : children) {
                if (ch != null) {
                    ch.scale(scale);
                }
            }
        }
    }

    public void removeChildAll() {
        children = new Object3dEx[childMax];
        childCnt = 0;
    }

    public void rotateChildren(float x, float y, float z) {
        if (children != null && children.length > 0) {
            for (Object3dEx ch : children) {
                if (ch != null) {
                    SimpleVector parentPosition = this.getTransformedCenter();
                    ch.rotateAroundVectorX(parentPosition, x);
                    ch.rotateAroundVectorY(parentPosition, y);
                    ch.rotateAroundVectorZ(parentPosition, z);
                }
            }
        }
    }

    public void rotateAroundVectorX(SimpleVector vector, float angle) {
        if (angle == 0) return;
        vector.x = 1;
        rotateAroundVector(vector, angle);
    }

    public void rotateAroundVectorY(SimpleVector vector, float angle) {
        if (angle == 0) return;
        vector.y = 1;
        rotateAroundVector(vector, angle);
    }

    public void rotateAroundVectorZ(SimpleVector vector, float angle) {
        if (angle == 0) return;
        vector.z = 1;
        rotateAroundVector(vector, angle);
    }

    public void rotateAroundVector(SimpleVector vector, float angle) {
        if (angle == 0) return;

        float c, s;
        Matrix m;
        boolean cachedAngle = false;

        if (cacheRotAng == angle) {
            c = cacheRotAngCos;
            s = cacheRotAngSin;
            cachedAngle = true;
        } else {
            cacheRotAng = angle;
            c = FloatMath.cos(angle);
            cacheRotAngCos = c;
            s = FloatMath.sin(angle);
            cacheRotAngSin = s;
        }

        if (cacheRotVec != null && cacheRotVec.equals(vector) && cachedAngle && cacheRotAxisMat != null) {
            m = cacheRotAxisMat;
        } else {
            cacheRotVec = vector;
            m = new Matrix();

            float a11 = c + (1 - c) * vector.x * vector.x;
            float a12 = (1 - c) * vector.x * vector.y - s * vector.z;
            float a13 = (1 - c) * vector.z * vector.x + s * vector.y;
            m.setRow(0, a11, a12, a13, 0);

            float a21 = (1 - c) * vector.x * vector.y + s * vector.z;
            float a22 = c + (1 - c) * vector.y * vector.y;
            float a23 = (1 - c) * vector.z * vector.y - s * vector.x;
            m.setRow(1, a21, a22, a23, 0);

            float a31 = (1 - c) * vector.z * vector.x - s * vector.y;
            float a32 = (1 - c) * vector.z * vector.y + s * vector.x;
            float a33 = c + (1 - c) * vector.z * vector.z;
            m.setRow(2, a31, a32, a33, 0);

            m.setRow(3, 0, 0, 0, 1);

            cacheRotAxisMat = m;
        }

        Matrix currentTransformMatrix = getWorldTransformation();
        currentTransformMatrix.matMul(m);
        clearTranslation();
        getRotationMatrix().setRow(3, 0, 0, 0, 1);
        setRotationMatrix(currentTransformMatrix);
    }
}


EgonOlsen

setRotationMatrix sets a 4x4 matrix as rotation matrix. If this matrix contains additional translations, shearing or scaling, this will affect the object too. It's not advised to code such operations into that matrix, but nobody prevents you from doing so.

There's no setTransformationMatrix() because a transformation matrix is the result of all other matrices (rotation, translation, scale, origin, child's...) multiplied. It makes sense to return it, but it doesn't make any to set it.

Alexey

I am a newbie in 3d & graphics, maybe i don't  understand some details and thinking differently, but i've been using intuitive methods by name.