// 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.fbotest) #include "rs_graphics.rsh" rs_program_vertex gPVBackground; rs_program_fragment gPFBackground; rs_allocation gTGrid; rs_program_store gPFSBackground; rs_font gItalic; rs_allocation gTextAlloc; rs_allocation gOffscreen; rs_allocation gOffscreenDepth; rs_allocation gReadBackTest; typedef struct MeshInfo { rs_mesh mMesh; int mNumIndexSets; float3 bBoxMin; float3 bBoxMax; } MeshInfo_t; MeshInfo_t *gMeshes; static float3 gLookAt; static float gRotateX; static float gRotateY; static float gZoom; static float gLastX; static float gLastY; void onActionDown(float x, float y) { gLastX = x; gLastY = y; } void onActionScale(float scale) { gZoom *= 1.0f / scale; gZoom = max(0.1f, min(gZoom, 500.0f)); } void onActionMove(float x, float y) { float dx = gLastX - x; float dy = gLastY - y; if (fabs(dy) <= 2.0f) { dy = 0.0f; } if (fabs(dx) <= 2.0f) { dx = 0.0f; } gRotateY -= dx; if (gRotateY > 360) { gRotateY -= 360; } if (gRotateY < 0) { gRotateY += 360; } gRotateX -= dy; gRotateX = min(gRotateX, 80.0f); gRotateX = max(gRotateX, -80.0f); gLastX = x; gLastY = y; } void init() { gRotateX = 0.0f; gRotateY = 0.0f; gZoom = 50.0f; gLookAt = 0.0f; } void updateMeshInfo() { rs_allocation allMeshes = rsGetAllocation(gMeshes); int size = rsAllocationGetDimX(allMeshes); gLookAt = 0.0f; float minX, minY, minZ, maxX, maxY, maxZ; for (int i = 0; i < size; i++) { MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); rsgMeshComputeBoundingBox(info->mMesh, &minX, &minY, &minZ, &maxX, &maxY, &maxZ); info->bBoxMin = (minX, minY, minZ); info->bBoxMax = (maxX, maxY, maxZ); gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f; } gLookAt = gLookAt / (float)size; } static void renderAllMeshes() { rs_allocation allMeshes = rsGetAllocation(gMeshes); int size = rsAllocationGetDimX(allMeshes); gLookAt = 0.0f; float minX, minY, minZ, maxX, maxY, maxZ; for (int i = 0; i < size; i++) { MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); rsgDrawMesh(info->mMesh); } } static void drawDescription() { uint width = rsgGetWidth(); uint height = rsgGetHeight(); int left = 0, right = 0, top = 0, bottom = 0; rsgBindFont(gItalic); rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom); } static void renderOffscreen(bool useDepth) { rsgBindColorTarget(gOffscreen, 0); if (useDepth) { rsgBindDepthTarget(gOffscreenDepth); rsgClearDepth(1.0f); } else { rsgClearDepthTarget(); } rsgClearColor(0.8f, 0.0f, 0.0f, 1.0f); rsgBindProgramVertex(gPVBackground); rs_matrix4x4 proj; float aspect = (float)rsAllocationGetDimX(gOffscreen) / (float)rsAllocationGetDimY(gOffscreen); rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); rsgProgramVertexLoadProjectionMatrix(&proj); rsgBindProgramFragment(gPFBackground); rsgBindProgramStore(gPFSBackground); rsgBindTexture(gPFBackground, 0, gTGrid); rs_matrix4x4 matrix; rsMatrixLoadIdentity(&matrix); // Position our models on the screen rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom); rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f); rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); rsgProgramVertexLoadModelMatrix(&matrix); renderAllMeshes(); // Render into the frambuffer rsgClearAllRenderTargets(); } static void drawOffscreenResult(int posX, int posY, rs_allocation texture) { // display the result rs_matrix4x4 proj, matrix; rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500); rsgProgramVertexLoadProjectionMatrix(&proj); rsMatrixLoadIdentity(&matrix); rsgProgramVertexLoadModelMatrix(&matrix); rsgBindTexture(gPFBackground, 0, texture); float startX = posX, startY = posY; float width = 256, height = 256; rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, startX, startY + height, 0, 0, 0, startX + width, startY + height, 0, 1, 0, startX + width, startY, 0, 1, 1); } int root(void) { rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); rsgClearDepth(1.0f); renderOffscreen(true); drawOffscreenResult(0, 0, gOffscreen); uint32_t w = rsAllocationGetDimX(gOffscreen); uint32_t h = rsAllocationGetDimY(gOffscreen); uint32_t numElements = w*h; rsgAllocationSyncAll(gOffscreen, RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET); rsAllocationCopy2DRange(gReadBackTest, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, w, h, gOffscreen, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); rsgAllocationSyncAll(gReadBackTest); drawOffscreenResult(0, 300, gReadBackTest); rsgBindProgramVertex(gPVBackground); rs_matrix4x4 proj; float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); rsgProgramVertexLoadProjectionMatrix(&proj); rsgBindProgramFragment(gPFBackground); rsgBindProgramStore(gPFSBackground); rsgBindTexture(gPFBackground, 0, gTGrid); rs_matrix4x4 matrix; rsMatrixLoadIdentity(&matrix); // Position our models on the screen rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom); rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f); rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); rsgProgramVertexLoadModelMatrix(&matrix); renderAllMeshes(); drawDescription(); return 0; }