blob: 4cdfc121ccdd1bb39417524d63486120950c4242 [file] [log] [blame]
/*
* Copyright (C) 2015 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.example.android.rs.vr.engine)
#pragma rs_fp_relaxed
int size;
int z;
rs_allocation volume;
static float sigmoid(float f) {
return (float) (1 / (1 + exp(f / 2)));
}
static float pillDistance(float3 p1, float3 p2, float3 img) {
if (dot(p2 - p1, img - p1) > 0 && dot(p1 - p2, img - p2) > 0) {
return length(cross(img - p1, img - p2)) / length(p2 - p1);
}
return min(distance(p1, img), distance(p2, img));
}
static short pill(float3 p1, float3 p2, float rad, short max, float3 img) {
return (short) (max * sigmoid(pillDistance(p1, p2, img) - rad));
}
static short cogPill(float3 p1, float3 p2, float rad, short max, float3 img) {
float3 vec = (p1 + p2) / 2 - img;
float angle = fabs(2 * fract(atan2pi(vec.z, vec.y) * 5) - 1);
return (short) (max
* sigmoid(pillDistance(p1, p2, img) - rad * (1 + angle / 2)));
}
static float cylinderDistance(float3 p1, float3 p2, float3 img) {
float dot1 = dot(p2 - p1, img - p1);
float dot2 = dot(p1 - p2, img - p2);
if (dot1 > 0 && dot2 > 0) {
return length(cross(img - p1, img - p2)) / length(p2 - p1);
}
return -dot1 * dot2;
}
static short cylinder(float3 p1, float3 p2, float rad, short max, float3 img) {
return (short) (max * sigmoid(cylinderDistance(p1, p2, img) - rad));
}
static short cogCylinder(float3 p1, float3 p2, float rad, short max, float3 img) {
float3 vec = (p1 + p2) / 2 - img;
float angle = fabs(2 * fract(atan2pi(vec.y, vec.x) * 6) - 1);
return (short) (max
* sigmoid(cylinderDistance(p1, p2, img) - rad * (1 + angle / 5)));
}
static float distanceCircle(float3 center, float radius, float3 normal,
float3 img) {
float3 pc = img - center;
float tmp1 = dot(normal, pc);
tmp1 = tmp1 * tmp1;
float tmp2 = (sqrt(length(pc) * length(pc) - tmp1) - radius);
return tmp1 + tmp2 * tmp2;
}
static short circle(float3 center, float circleRadius, float3 normal, float rad,
short max, float3 img) {
return (short) (max
* sigmoid(distanceCircle(center, circleRadius, normal, img) - rad));
}
static float distanceDisk(float3 center, float radius, float3 normal,
float3 img) {
float3 pc = img - center;
float tmp1 = dot(normal, pc);
tmp1 = tmp1 * tmp1;
float tmp2 = (sqrt(length(pc) * length(pc) - tmp1) - radius);
if (length(pc - dot(normal, pc) * normal) > radius) {
return (tmp1 + tmp2 * tmp2);
}
return tmp1;
}
static short disk(float3 center, float circleRadius, float3 normal, float rad,
short max, float3 img) {
return (short) (max
* sigmoid(distanceDisk(center, circleRadius, normal, img) - rad));
}
static short cogDisk(float3 center, float circleRadius, float3 normal,
float rad, short max, float3 img) {
float3 vec = center - img;
float angle = fabs(2 * fract(atan2pi(vec.y, vec.x) * 20) - 1);
return (short) (max
* sigmoid(
distanceDisk(center, circleRadius * (1 + angle / 10),
normal, img) - rad));
}
static float andyBody(float3 img) {
short v = 0;
{ // body
float3 p1 = { size * 0.5f, size * 0.5f, size * 0.3f };
float3 p2 = { size * 0.5f, size * 0.5f, size * 0.65f };
float radius = size * 0.22f;
v = max(v, cylinder(p1, p2, radius, 144, img));
p2.z = size * 0.4f;
v = max(v, pill(p1, p2, radius, 144, img));
float3 normal = { 0.0f, 0.0f, 1.0f };
v -= circle(p1, radius*0.9f, normal, size * 0.05, 144, img);
}
float armOffset = 0.27f;
{ // arm 1
float3 p1 = { size * (0.5f - armOffset), size * 0.5f, size * 0.4f };
float3 p2 = { size * (0.5f - armOffset), size * 0.5f, size * 0.57f };
v = max(v, pill(p1, p2, size * 0.09f, 144, img));
}
{ // arm 2
float3 p1 = { size * (0.5f + armOffset), size * 0.5f, size * 0.4f };
float3 p2 = { size * (0.5f + armOffset), size * 0.5f, size * 0.57f };
v = max(v, pill(p1, p2, size * 0.09f, 144, img));
}
{ // leg 1
float3 p1 = { size * 0.6f, size * 0.5f, size * 0.6f };
float3 p2 = { size * 0.6f, size * 0.5f, size * 0.8f };
v = max(v, pill(p1, p2, size * 0.08f, 144, img));
}
{ // leg 2
float3 p1 = { size * 0.4f, size * 0.5f, size * 0.6f };
float3 p2 = { size * 0.4f, size * 0.5f, size * 0.8f };
v = max(v, pill(p1, p2, size * 0.08f, 144, img));
}
float3 p1 = { size * 0.5f, size * 0.5f, size * 0.3f };
;
{ // antenna
float spacex = .1;
float3 p2 = { size * (0.5f - spacex), size * 0.5f, size * 0.07f };
v = max(v, pill(p1, p2, size * 0.017f, 400, img));
float3 p3 = { size * (0.5f + spacex), size * 0.5f, size * 0.07f };
v = max(v, pill(p1, p3, size * 0.017f, 400, img));
}
{ // eyes
float spacex = .105;
float3 p2 = { size * (0.5f - spacex), size * 0.4f, size * 0.2f };
float3 p3 = { size * (0.5f + spacex), size * 0.4f, size * 0.2f };
v -= pill(p2, p2, size * 0.018f, 144, img);
v -= pill(p3, p3, size * 0.018f, 144, img);
v = max(v, pill(p1, p2, size * 0.032f, 400, img));
v = max(v, pill(p1, p3, size * 0.032f, 400, img));
}
return v;
}
static float andySkeleton(float3 img) {
short v = 0;
{ // body
float3 p1 = { size * 0.5f, size * 0.5f, size * 0.3f };
float radius = size * 0.15f;
float3 normal = { 0.0f, 0.0f, 1.0f };
for (int i = 0; i < 5; i++) {
p1.z += size * 0.04;
v += circle(p1, radius, normal, size * 0.07, 400, img);
}
p1.z = size * 0.3f;
float3 p2 = { size * 0.5f, size * 0.5f, size * 0.6f };
v = max(v, cogDisk(p2, radius*0.7f, normal, size * 0.07, 400, img));
v = max(v, cogCylinder(p1, p2, size * 0.04, 400, img));
}
float armOffset = 0.27f;
{
float3 p1 = { size * (0.5f - armOffset), size * 0.5f, size * 0.4f };
float3 p2 = { size * (0.5f + armOffset), size * 0.5f, size * 0.4f };
v = max(v, cogPill(p1, p2, size * 0.02f, 400, img));
}
{ // arm 1
float3 p1 = { size * (0.5f - armOffset), size * 0.5f, size * 0.4f };
float3 p2 = { size * (0.5f - armOffset), size * 0.5f, size * 0.57f };
v = max(v, pill(p1, p2, size * 0.02f, 400, img));
}
{ // arm 2
float3 p1 = { size * (0.5f + armOffset), size * 0.5f, size * 0.4f };
float3 p2 = { size * (0.5f + armOffset), size * 0.5f, size * 0.57f };
v = max(v, pill(p1, p2, size * 0.02f, 400, img));
}
{ // leg 1
float3 p1 = { size * 0.6f, size * 0.5f, size * 0.6f };
float3 p2 = { size * 0.6f, size * 0.5f, size * 0.8f };
v = max(v, pill(p1, p2, size * 0.02f, 400, img));
}
{ // leg 2
float3 p1 = { size * 0.4f, size * 0.5f, size * 0.6f };
float3 p2 = { size * 0.4f, size * 0.5f, size * 0.8f };
v = max(v, pill(p1, p2, size * 0.02f, 400, img));
}
return v;
}
short __attribute__((kernel)) andy(uint32_t x, uint32_t y) {
float3 img = { x, y, z };
float v = andyBody(img);
v = max(v, andySkeleton(img));
return v;
}
void __attribute__((kernel)) copy(short in, uint32_t x, uint32_t y) {
rsSetElementAt_short(volume, in, x, y, z);
}