Created
December 8, 2016 13:18
Star
You must be signed in to star a gist
Sourcecode for Carrot Man: https://www.yousry.de/?p=8395&preview=true
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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