Skip to content

Instantly share code, notes, and snippets.

@yousry
Created December 8, 2016 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yousry/d6921852491457b45073350b4d52ae01 to your computer and use it in GitHub Desktop.
Save yousry/d6921852491457b45073350b4d52ae01 to your computer and use it in GitHub Desktop.
Sourcecode for Carrot Man: https://www.yousry.de/?p=8395&preview=true
//
// Carrot.mm
//
// Created by Yousry Abdallah.
// Copyright 2016 yousry.de. All rights reserved.
#include <string>
#import "YATextureArray.h"
#import "YATextureManager.h"
#import "YAImpersonatorInstanced.h"
#import "YAProbability.h"
#import "YAPreferences.h"
#import "YAEXRImageLoader.h"
#import "YASoundCollector.h"
#import "YAOpenAL.h"
#ifdef __linux__
#import "HIDReader.h"
#endif
#import "YASpotLight.h"
#import "YAGouradLight.h"
#import "YAQuaternion.h"
#import "YATransformator.h"
#import "YAMaterial.h"
#import "YAImpersonatorInstanced.h"
#import "YAIngredient.h"
#import "YAPerspectiveProjectionInfo.h"
#import "YAQuaternion.h"
#import "YAVector4f.h"
#import "YAVector3f.h"
#import "YAVector2f.h"
#import "YAVector2i.h"
#import "YATransformator.h"
#import "YARenderLoop.h"
#import "YALog.h"
#import "YADefenderUtils.h"
#import "BlenderSceneImporter.h"
#import "YAOpenAL.h"
#import "Carrot.h"
static const NSString* TAG = @"Carrot";
static const double ZFAR = 100.0f;
using namespace defender;
#define clamp(x,y,z) fminf(fmaxf(x,y),z)
@interface Carrot ()
{
YADefenderUtils* defenderUtils;
BlenderSceneImporter *blenderSceneImporter;
__block NSArray *carrotImps;
__block YAImpersonator *carrotSphere;
__block YAVector3f* lookAt;
YAOpenAL *openAL;
}
@end
@implementation Carrot : NSObject
- (id) initIn: (YARenderLoop*) loop
{
[YALog debug:TAG message:@"initIn"];
self = [super init];
if(self) {
renderLoop = loop;
defenderUtils = [[YADefenderUtils alloc] initIn: renderLoop];
}
return self;
}
- (void) setup
{
[YALog debug:TAG message:@"setup scene"];
// Load lively music and place it direct between the ears.
openAL = [[YAOpenAL alloc] initInWorld: renderLoop];
openAL.baseVolume = 100;
int srcB = [openAL loadOgg: @"pianoRoll.ogg"];
int srcID = [openAL setupSound:srcB atPosition: [[YAVector3f alloc] init] loop:NO];
[openAL playSound: srcID];
// Import Blender Scene
blenderSceneImporter = [[BlenderSceneImporter alloc] initIn:renderLoop];
[blenderSceneImporter load:@"carrot"];
// The Brown thingies are badly modelled (not cloesed).
carrotImps = [defenderUtils getImpsForIngredient:@"carrotCarrot"];
for(YAImpersonator* imp in carrotImps) {
imp.backfaceCulling = false;
}
// find the clump in the scene graph
carrotSphere = [defenderUtils getImpForIngredient:@"carrotSphere"];
[self interactiveSetup];
[self thingySetup];
[self ballSetup];
[self rotateTree];
renderLoop.transformer.projectionInfo.zNear = 0.1;
renderLoop.transformer.projectionInfo.zFar = ZFAR;
[[renderLoop transformer] recalcCam];
// save shadowbuffer memory by updating the spotlight frustum.
renderLoop.shadowTransformer.projectionInfo.zNear = 0.1f;
renderLoop.shadowTransformer.projectionInfo.zFar = 10.0f;
[[renderLoop shadowTransformer] recalcCam];
[defenderUtils showFPSandFrame];
// Activation FXAA for Screen Recording.
renderLoop.deferred = YES;
renderLoop.bloom = NO;
// Loading HDR Background.
[renderLoop setSkyMap:@"IMG_0741_Panorama_sphere"];
[renderLoop createLightProbe:@"IMG_0741_Panorama_sphere" Position: [[YAVector3f alloc] init]];
renderLoop.showSkyMap = YES;
[renderLoop setTraceMouseMove:YES];
[renderLoop changeImpsSortOrder:SORT_IDENTITY_ALPHA];
[renderLoop resetAnimators];
[renderLoop setMultiSampling:YES];
[renderLoop setActiveAnimation:true];
renderLoop.drawScene = YES;
}
- (void) rotateTree
{
// The blender importer uses quats. Therefore I cannot use a sinple parameter modifier.
YAImpersonator* crTB = [defenderUtils getImpForIngredient:@"CarrotTreeB"];
__block YAQuaternion *qTB = crTB.rotationQuaternion.copy;
YABlockAnimator *aTB = [renderLoop createBlockAnimator];
aTB.progress = harmonic;
aTB.interval = 7.0f;
[aTB addListener:^(float spanPos, NSNumber* event, int message) {
YAQuaternion *rot = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: spanPos * 360.0f * 2];
[crTB.rotationQuaternion setQuat: [qTB mulQuaternion: rot]];
}];
YAImpersonator* crTC = [defenderUtils getImpForIngredient:@"CarrotTreeC"];
__block YAQuaternion *qTC = crTC.rotationQuaternion.copy;
YABlockAnimator *aTC = [renderLoop createBlockAnimator];
aTC.progress = harmonic;
aTC.interval = 7.25f;
[aTC addListener:^(float spanPos, NSNumber* event, int message) {
YAQuaternion *rot = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: spanPos * 360.0f * 2];
[crTC.rotationQuaternion setQuat: [qTC mulQuaternion: rot]];
}];
}
-(void) ballSetup
{
__block YAQuaternion *orgRot = carrotSphere.rotationQuaternion.copy;
__block YAVector3f* orgPos = carrotSphere.translation.copy;
YABlockAnimator *anim = [renderLoop createBlockAnimator];
anim.asyncProcessing = false;
anim.delay = 1.8f;
__block float start = -1.0f;
__block float last = start;
[anim addListener:^(float spanPos, NSNumber* event, int message)
{
// Alternatively setup timeline scheduler
if(start < 0) {
start = YALog.glfwGetTime;
last = start;
return;
}
float now = YALog.glfwGetTime;
float duration = now - start;
// 1/50 Steps
float r = duration * 50.0f;
YAQuaternion *rot = [[YAQuaternion alloc] initEulerDeg: r pitch: 0 roll: 0 ];
// Rotation around center.
YAVector3f* newPos = [rot rotate: orgPos];
[carrotSphere.translation setVector: newPos];
// This is the rotation during straight movement 0.595 it the sphere radius.
YAQuaternion *rotU = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0.595 * 2.0f * M_PI * r roll: 0 ];
// The sphere heading is identical to its z rotation
YAQuaternion *rotUU = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: r ];
// Apply heading to the sphere rotation
YAQuaternion *rotUUU =[rotUU mulQuaternion: rotU];
// Update the orientation
[carrotSphere.rotationQuaternion setQuat: [orgRot mulQuaternion: rotUUU] ];
}];
}
-(void) thingySetup
{
for(int i = 0; i < 4; i++) {
YABlockAnimator *animA = [renderLoop createBlockAnimator];
animA.asyncProcessing = false;
animA.progress = cyclic;
animA.delay = (3 - i) * 1.8;
animA.interval = 7.2f;
// Accordion calculation. rotations adds up. No need for a Subspace or Armature.
__block YAImpersonator* impB = carrotImps[1 + i * 4];
YAQuaternion *orgRotB = impB.rotationQuaternion.copy;
__block YAImpersonator* impC = carrotImps[2 + i * 4];
YAQuaternion *orgRotC = impC.rotationQuaternion.copy;
__block YAImpersonator* impD = carrotImps[3 + i * 4];
YAQuaternion *orgRotD = impD.rotationQuaternion.copy;
[animA addListener:^(float spanPos, NSNumber* event, int message)
{
// acelleration and decelleration .
float d = sin(spanPos * M_PI);
// addin to a nearly 90 degree rotation.
YAQuaternion *rotB = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: d * 45.0f];
YAQuaternion *rotC = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: d * 45.0f * 2];
YAQuaternion *rotD = [[YAQuaternion alloc] initEulerDeg: 0 pitch: 0 roll: d * 45.0f * 2.98];
// Update Rotation
[impB.rotationQuaternion setQuat: [orgRotB.copy mulQuaternion: rotB]];
[impC.rotationQuaternion setQuat: [orgRotC.copy mulQuaternion: rotC]];
[impD.rotationQuaternion setQuat: [orgRotD.copy mulQuaternion: rotD]];
}];
}
}
- (void) interactiveSetup
{
// Update the View according to mousemovement
__block YAVector2i* mouseVector = nil;
__block YAVector2f* force = [[YAVector2f alloc] init];
__block float actHead = 0;
__block float actPitch = 0;
__block float distance = 1.2 * [defenderUtils.avatar.position distanceTo: lookAt];
__block float actDistance = distance;
const float defaultDistance = distance;
const float reducedDistance = distance / 1.5f;
YABlockAnimator* mausi = [renderLoop createBlockAnimator];
// HID recording (Mouse) > 400HZ
mausi.asyncProcessing = YES;
[mausi addListener:^(float spanPos, NSNumber* event, int message)
{
event_keyPressed ev = (event_keyPressed)event.intValue;
if(ev == MOUSE_VECTOR) {
// Mouse inpulses are bit encoded.
mouseVector = [[YAVector2i alloc] initVals:(message >> 16) :message & 511];
const float x = ((mouseVector.x / 512.0f) - 0.5f) * 1.0f;
const float y = ((mouseVector.y / 512.0f) - 0.5f) * 1.0f;
force.x = x;
force.y = y;
// SPACE changes the distance.
} else if(ev == SPACE) {
if(message != 0) {
distance = distance < defaultDistance ? defaultDistance : reducedDistance;
}
}
}];
YABlockAnimator* looki = [renderLoop createBlockAnimator];
looki.asyncProcessing = false;
looki.progress = harmonic;
looki.interval = 2.5f;
[looki addListener:^(float spanPos, NSNumber* event, int message)
{
actHead += force.x * 1.6;
actPitch -= force.y;
// limit the movements to avoid ugly perspectives.
actPitch = clamp(actPitch, 10.0f, 45.0f);
actHead = fmodf(actHead + 360.0f, 360.0f);
YAQuaternion* rot = [[YAQuaternion alloc] initEulerDeg: actHead pitch: actPitch roll: 0];
YAVector3f* pos = [[YAVector3f alloc] initZAxis];
// set the position step size.
if(actDistance < distance)
actDistance += 0.05f;
else if(actDistance > distance)
actDistance -= 0.05f;
// set the distance step size.
if(actDistance < reducedDistance)
actDistance = reducedDistance;
else if(actDistance > defaultDistance)
actDistance = defaultDistance;
// pos is already normailzed
[pos mulScalar: -actDistance];
// Update View and frustum.
[[defenderUtils.avatar position] setVector: [rot rotate: pos]];
[defenderUtils.avatar lookAt: carrotSphere.translation];
}];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment