// Copyright (C) 2011 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma version(1) #pragma rs java_package_name(com.android.modelviewer) #include "scenegraph_objects.rsh" rs_script gTransformScript; typedef struct { int changed; rs_matrix4x4 *mat; } ParentData; //#define DEBUG_TRANSFORMS /* Unused function: static void debugTransform(SgTransform *data, const ParentData *parent) { rsDebug("****** ******", (int)data); printName(data->name); rsDebug("isDirty", data->isDirty); rsDebug("parent", (int)parent); rsDebug("child ", rsIsObject(data->children)); // Refresh matrices if dirty if (data->isDirty && rsIsObject(data->components)) { uint32_t numComponenets = rsAllocationGetDimX(data->components); for (int i = 0; i < numComponenets; i ++) { const SgTransformComponent *comp = NULL; comp = (const SgTransformComponent *)rsGetElementAt(data->components, i); if (rsIsObject(comp->name)) { rsDebug((const char*)rsGetElementAt(comp->name, 0), comp->value); rsDebug("Type", comp->type); } else { rsDebug("no name", comp->value); rsDebug("Type", comp->type); } } } rsDebug("timestamp", data->timestamp); rsDebug("****** ******", (int)data); } */ static void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) { rs_matrix4x4 temp; switch (type) { case TRANSFORM_TRANSLATE: rsMatrixLoadTranslate(&temp, data.x, data.y, data.z); break; case TRANSFORM_ROTATE: rsMatrixLoadRotate(&temp, data.w, data.x, data.y, data.z); break; case TRANSFORM_SCALE: rsMatrixLoadScale(&temp, data.x, data.y, data.z); break; } rsMatrixMultiply(mat, &temp); } void root(const rs_allocation *v_in, rs_allocation *v_out, const void *usrData) { SgTransform *data = (SgTransform *)rsGetElementAt(*v_in, 0); const ParentData *parent = (const ParentData *)usrData; #ifdef DEBUG_TRANSFORMS debugTransform(data, parent); #endif //DEBUG_TRANSFORMS rs_matrix4x4 *localMat = &data->localMat; rs_matrix4x4 *globalMat = &data->globalMat; // Refresh matrices if dirty if (data->isDirty && rsIsObject(data->components)) { bool resetLocal = false; uint32_t numComponenets = rsAllocationGetDimX(data->components); for (int i = 0; i < numComponenets; i ++) { if (!resetLocal) { // Reset our local matrix only for component transforms rsMatrixLoadIdentity(localMat); resetLocal = true; } const SgTransformComponent *comp = NULL; comp = (const SgTransformComponent *)rsGetElementAt(data->components, i); appendTransformation(comp->type, comp->value, localMat); } } if (parent) { data->isDirty = (parent->changed || data->isDirty) ? 1 : 0; if (data->isDirty) { rsMatrixLoad(globalMat, parent->mat); rsMatrixMultiply(globalMat, localMat); } } else if (data->isDirty) { rsMatrixLoad(globalMat, localMat); } ParentData toChild; toChild.changed = 0; toChild.mat = globalMat; if (data->isDirty) { toChild.changed = 1; data->timestamp ++; } if (rsIsObject(data->children)) { rs_allocation nullAlloc = {0}; rsForEach(gTransformScript, data->children, nullAlloc, &toChild, sizeof(toChild)); } data->isDirty = 0; }