diff --git a/Samples/GVRKit/GVRHeadPose.h b/Samples/GVRKit/GVRHeadPose.h deleted file mode 100644 index 1f0467e..0000000 --- a/Samples/GVRKit/GVRHeadPose.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-modular-include-in-framework-module" -#include "vr/gvr/capi/include/gvr.h" -#include "vr/gvr/capi/include/gvr_audio.h" -#include "vr/gvr/capi/include/gvr_types.h" -#pragma clang diagnostic pop - -/** - * @enum GVREye - * - * Enumeration of the left and right eyes, used to identify the correct - * rendering parameters needed for stereo rendering. - */ -typedef NS_ENUM(NSInteger, GVREye) { - kGVRLeftEye = GVR_LEFT_EYE, /**< Left eye. */ - kGVRRightEye = GVR_RIGHT_EYE, /**< Right eye. */ - kGVRCenterEye, /**< Center eye. */ -}; - -/** - * Defines a struct to hold half field of view angles, in degrees. - */ -typedef struct { - CGFloat left; - CGFloat right; - CGFloat bottom; - CGFloat top; -} GVRFieldOfView; - -/** - * Defines a class that provides current head pose transforms. - */ -@interface GVRHeadPose : NSObject - -/** The current |GVREye| eye being rendered with the head pose. */ -@property(nonatomic, readonly) GVREye eye; - -/** The head pose transform matrix. Includes manual yaw and pitch rotations. */ -@property(nonatomic, readonly) GLKMatrix4 headTransform; - -/** The eye transform relative to the head transform. For monoscopic this is identity matrix. */ -@property(nonatomic, readonly) GLKMatrix4 eyeTransform; - -/** The view (camera) transform that is the composite of head and eye transforms. */ -@property(nonatomic, readonly) GLKMatrix4 viewTransform; - -/** The projection transform computed from ::setProjectionMatrixWithNear:Far: */ -@property(nonatomic, readonly) GLKMatrix4 projectionTransform; - -/** The current display viewport. */ -@property(nonatomic, readonly) CGRect viewport; - -/** The current field of view. This depends on paired Cardboard viewer in stereoscopic mode. */ -@property(nonatomic, readonly) GVRFieldOfView fieldOfView; - -/** The timestamp when this frame will be presented. */ -@property(nonatomic, readonly) NSTimeInterval nextFrameTime; - -/** - * Computes the projection matrix with near and far planes and is accessed from projectionTransform - * property. - */ -- (void)setProjectionMatrixWithNear:(CGFloat)near far:(CGFloat)far; - -/** Returns the projection matrix given near and far planes. */ -- (GLKMatrix4)projectionMatrixWithNear:(CGFloat)near far:(CGFloat)far; - -@end diff --git a/Samples/GVRKit/GVRHeadPose.mm b/Samples/GVRKit/GVRHeadPose.mm deleted file mode 100644 index d8e0dad..0000000 --- a/Samples/GVRKit/GVRHeadPose.mm +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRHeadPose.h" - -// For monoscopic rendering, define 45 degree half angle horizontally and vertically. -static const float kMonoFieldOfView = 45.0f; - -namespace { - -static void GVRMatrixToGLKMatrix4(const gvr::Mat4f &matrix, GLKMatrix4 *glkMatrix) { - // Note that this performs a *tranpose* to a column-major matrix array, as - // expected by GL. - float result[16]; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - result[j * 4 + i] = matrix.m[i][j]; - } - } - *glkMatrix = GLKMatrix4MakeWithArray(result); -} - -static gvr::Recti CalculatePixelSpaceRect(const gvr::Sizei &size, const gvr::Rectf &source_rect) { - float width = static_cast(size.width); - float height = static_cast(size.height); - gvr::Rectf rect = {source_rect.left * width, source_rect.right * width, - source_rect.bottom * height, source_rect.top * height}; - gvr::Recti result = {static_cast(rect.left), static_cast(rect.right), - static_cast(rect.bottom), static_cast(rect.top)}; - return result; -} - -static gvr::Mat4f PerspectiveMatrixFromView(const GVRFieldOfView &fov, float z_near, float z_far) { - gvr::Mat4f result; - const float x_left = -std::tan(fov.left * M_PI / 180.0f) * z_near; - const float x_right = std::tan(fov.right * M_PI / 180.0f) * z_near; - const float y_bottom = -std::tan(fov.bottom * M_PI / 180.0f) * z_near; - const float y_top = std::tan(fov.top * M_PI / 180.0f) * z_near; - const float zero = 0.0f; - - assert(x_left < x_right && y_bottom < y_top && z_near < z_far && z_near > zero && z_far > zero); - const float X = (2 * z_near) / (x_right - x_left); - const float Y = (2 * z_near) / (y_top - y_bottom); - const float A = (x_right + x_left) / (x_right - x_left); - const float B = (y_top + y_bottom) / (y_top - y_bottom); - const float C = (z_near + z_far) / (z_near - z_far); - const float D = (2 * z_near * z_far) / (z_near - z_far); - - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - result.m[i][j] = 0.0f; - } - } - result.m[0][0] = X; - result.m[0][2] = A; - result.m[1][1] = Y; - result.m[1][2] = B; - result.m[2][2] = C; - result.m[2][3] = D; - result.m[3][2] = -1; - - return result; -} - -} // namespace - -@implementation GVRHeadPose { - UIInterfaceOrientation _orientation; - gvr::Sizei _renderSize; - CGFloat _yaw; - CGFloat _pitch; -} - -- (instancetype)init { - if (self = [super init]) { - _yaw = _pitch = 0.0f; - } - return self; -} - -- (void)setHeadPose:(gvr::Mat4f &)headPose - renderSize:(gvr::Sizei)renderSize - orientation:(UIInterfaceOrientation)orientation - nextFrameTime:(NSTimeInterval)nextFrameTime { - // Next frame time. - _nextFrameTime = nextFrameTime; - - // Eye. - _eye = kGVRCenterEye; - - // Head transform. - GVRMatrixToGLKMatrix4(headPose, &_headTransform); - - // Apply yaw rotation. - _headTransform = GLKMatrix4Multiply(_headTransform, GLKMatrix4MakeYRotation(_yaw)); - - // For pitch rotation we have to take the interface orientation into account. GVR always draws in - // landscape right orientation, where the pitch is correctly applied to X axis. But in portrait - // mode, we apply the pitch to the Y axis. - if (UIInterfaceOrientationIsLandscape(_orientation)) { - _headTransform = GLKMatrix4Multiply(GLKMatrix4MakeXRotation(_pitch), _headTransform); - } else { - _headTransform = GLKMatrix4Multiply(GLKMatrix4MakeYRotation(_pitch), _headTransform); - } - - // Eye transform. - _eyeTransform = GLKMatrix4Identity; - - // View transform. - _viewTransform = _headTransform; - - // Viewport. - _renderSize = renderSize; - _viewport = CGRectMake(0, 0, _renderSize.width, _renderSize.height); - - // Field of view. - const float aspect_ratio = (float)_renderSize.width / (float)_renderSize.height; - float vertFov = kMonoFieldOfView; - float horizFov = - std::atan(aspect_ratio * std::tan(kMonoFieldOfView * M_PI / 180.0f)) * 180 / M_PI; - _fieldOfView = {horizFov, horizFov, vertFov, vertFov}; - - _orientation = orientation; -} - -- (void)setEyePose:(gvr::Mat4f &)eyePose - forEye:(GVREye)eye - bufferViewport:(gvr::BufferViewport *)bufferViewport { - // Eye. - _eye = eye; - - // Eye transform. - GVRMatrixToGLKMatrix4(eyePose, &_eyeTransform); - - // View transform. - _viewTransform = GLKMatrix4Multiply(_eyeTransform, _headTransform); - - // Viewport. - gvr::Recti pixel_rect = CalculatePixelSpaceRect(_renderSize, bufferViewport->GetSourceUv()); - _viewport = CGRectMake(pixel_rect.left, - pixel_rect.bottom, - pixel_rect.right - pixel_rect.left, - pixel_rect.top - pixel_rect.bottom); - - // Field of view. - const gvr::Rectf &fov = bufferViewport->GetSourceFov(); - _fieldOfView = {fov.left, fov.right, fov.bottom, fov.top}; -} - -- (void)addToHeadRotationYaw:(CGFloat)yaw andPitch:(CGFloat)pitch { - _yaw += yaw; - _pitch += pitch; -} - -- (void)resetHeadRotation { - _yaw = _pitch = 0.0f; -} - -- (void)setProjectionMatrixWithNear:(CGFloat)near far:(CGFloat)far { - _projectionTransform = [self projectionMatrixWithNear:near far:far]; -} - -- (GLKMatrix4)projectionMatrixWithNear:(CGFloat)near far:(CGFloat)far { - gvr::Mat4f perspective = PerspectiveMatrixFromView(_fieldOfView, near, far); - GLKMatrix4 transform; - GVRMatrixToGLKMatrix4(perspective, &transform); - return GLKMatrix4Multiply(transform, [self interfaceRotationFromOrientation:_orientation]); -} - -- (GLKMatrix4)interfaceRotationFromOrientation:(UIInterfaceOrientation)orientation { - // Compute interface rotation matrix based on interface orientation. - switch (orientation) { - case UIInterfaceOrientationPortrait: - return GLKMatrix4MakeZRotation(-M_PI_2); - break; - case UIInterfaceOrientationPortraitUpsideDown: - return GLKMatrix4MakeZRotation(M_PI_2); - break; - case UIInterfaceOrientationLandscapeLeft: - return GLKMatrix4MakeZRotation(M_PI); - break; - - case UIInterfaceOrientationLandscapeRight: - default: - return GLKMatrix4Identity; - break; - } -} - -@end diff --git a/Samples/GVRKit/GVRImageRenderer.h b/Samples/GVRKit/GVRImageRenderer.h deleted file mode 100644 index 05a44fb..0000000 --- a/Samples/GVRKit/GVRImageRenderer.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRTextureRenderer.h" - -/** Defines a texture renderer for images. */ -@interface GVRImageRenderer : GVRTextureRenderer - -/** Initialize texture renderer from given image. */ -- (instancetype)initWithImage:(UIImage *)image; - -/** Initialize texture renderer from an image from the given path. */ -- (instancetype)initWithContentsOfFile:(NSString *)path; - -@end diff --git a/Samples/GVRKit/GVRImageRenderer.mm b/Samples/GVRKit/GVRImageRenderer.mm deleted file mode 100644 index 9eade74..0000000 --- a/Samples/GVRKit/GVRImageRenderer.mm +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRImageRenderer.h" - -@implementation GVRImageRenderer { - dispatch_block_t _textureLoader; -} - -- (instancetype)initWithContentsOfFile:(NSString *)path { - if (self = [super init]) { - // Defer loading until the renderer is initialized. - __weak __typeof(self) weakSelf = self; - _textureLoader = ^{ - GLKTextureLoader *loader = - [[GLKTextureLoader alloc] initWithSharegroup:EAGLContext.currentContext.sharegroup]; - [loader textureWithContentsOfFile:path - options:nil - queue:NULL - completionHandler:^(GLKTextureInfo *textureInfo, NSError *outError) { - __strong __typeof(self) strongSelf = weakSelf; - if (textureInfo) { - // Allow non-power of 2 sized textures. - glBindTexture(textureInfo.target, textureInfo.name); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - [strongSelf setImageTextureId:textureInfo.name]; - } - }]; - }; - } - return self; -} - -- (instancetype)initWithImage:(UIImage *)image { - if (self = [super init]) { - // Defer loading until the renderer is initialized. - __weak __typeof(self) weakSelf = self; - _textureLoader = ^{ - GLKTextureLoader *loader = - [[GLKTextureLoader alloc] initWithSharegroup:EAGLContext.currentContext.sharegroup]; - [loader textureWithCGImage:image.CGImage - options:nil - queue:NULL - completionHandler:^(GLKTextureInfo *textureInfo, NSError *outError) { - __strong __typeof(self) strongSelf = weakSelf; - if (textureInfo) { - // Allow non-power of 2 sized textures. - glBindTexture(textureInfo.target, textureInfo.name); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - [strongSelf setImageTextureId:textureInfo.name]; - } - }]; - }; - } - return self; -} - -#pragma mark - GVRTextureRenderer - -- (void)initializeGl { - [super initializeGl]; - // Load the texture once GL is initialized. - if (_textureLoader) { - _textureLoader(); - } -} - -@end diff --git a/Samples/GVRKit/GVRKit.h b/Samples/GVRKit/GVRKit.h deleted file mode 100644 index d4087b3..0000000 --- a/Samples/GVRKit/GVRKit.h +++ /dev/null @@ -1,11 +0,0 @@ -// Umbrella header file for all GVRKit headers. -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import diff --git a/Samples/GVRKit/GVRRenderer.h b/Samples/GVRKit/GVRRenderer.h deleted file mode 100644 index 9f45df5..0000000 --- a/Samples/GVRKit/GVRRenderer.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import - -#import "GVRHeadPose.h" - -/** - * Defines a class that provides rendering of monoscopic and stereoscopic (VR) - * content to display of the mobile device. The property ::VRModeEnabled controls - * the display of monoscopic vs. stereoscopic content. - * - * This class is meant to be subclassed in order to implement application specific rendering. - * Subclasses should override ::update:, ::draw and ::handleTrigger methods. - * - * Call ::initializeGl and ::clearGl before and after rendering on a valid GL context. Application - * should call ::drawFrame: on every iteration of the render loop on a valid GL context. The - * ::pause method should be called to pause head tracking and rendering. - * - * Although this class makes no assumption of threading context, it has been tested to be used - * only on the main thread. - * - * Applications can manually add yaw and pitch rotation to the current head pose. - */ -@interface GVRRenderer : NSObject - -/** - * The vrModeEnabled property allows switching between monoscopic and stereoscopic (VR) rendering. - * Stereoscopic rendering should be enabled only in fullscreen mode. - */ -@property(nonatomic) BOOL VRModeEnabled; - - -/** Initializes GL resources used by GVR. This should be called on a valid GL context. */ -- (void)initializeGl; - -/** Releases GL resources used by GVR. This should be called on a valid GL context. */ -- (void)clearGl; - -/** - * Draws the monoscopic or stereoscopic frame depending upon VRModeEnabled property. Calls - * ::draw:headPose method of subclasses to perform the actual drawing. This method should - * be called on every iteration of the render loop. - * - * @param nextFrameTime The timestamp of when the frame will be rendered to the display. - */ -- (void)drawFrame:(NSTimeInterval)nextFrameTime; - -/** - * Updates the rendering based on currently paired viewer profile. Call this if the user - * pairs a Cardboard viewer. - */ -- (void)refresh; - -/** - * Calls the method ::handleTriger: with the current head pose. Returns YES if - * the subclasses handled this method. - */ -- (BOOL)handleTrigger; - -/** - * Add yaw and pitch rotation to the current head pose. This should be the delta - * from the last update. Internally, this is cumulatively applied to the current - * head pose. See ::resetHeadRotation to clear additional rotation. - */ -- (void)addToHeadRotationYaw:(CGFloat)yaw andPitch:(CGFloat)pitch; - -/** - * Clears any additional yaw and pitch rotation applied to the current head pose. - * This method also recenters head tracking. - */ -- (void)resetHeadRotation; - -/** - * Call this when the render display size changes, including the current interface - * orientation. When ::VRModeEnabled is set to YES, the size should be fullscreen - * and orientation should be UIInterfaceOrientationLandscapeRight. - */ -- (void)setSize:(CGSize)size andOrientation:(UIInterfaceOrientation)orientation; - -/** - * Pauses or resumes head tracking and rendering. Subclasses should superclass's implementation. - * @param pause YES to pause and NO to resume. - */ -- (void)pause:(BOOL)pause; - -/** - * Subclasses should override this method to prepare for drawing with the - * supplied head pose. This is called for every frame, once per frame. - */ -- (void)update:(GVRHeadPose *)headPose; - -/** - * Subclasses should override this method to draw the content for the supplied - * head pose. This would be called every frame, once for monoscopic and twice for - * stereoscopic rendering. For stereoscopic rendering, the headpose will contain - * eye transform matrix. - */ -- (void)draw:(GVRHeadPose *)headPose; - -/** - * Subclasses should override this method to handle user pressing the trigger in the - * Cardboard viewer. They should return YES if the trigger action is handled. - * @param headPose The headpose used to draw the view. - */ -- (BOOL)handleTrigger:(GVRHeadPose *)headPose; - -@end diff --git a/Samples/GVRKit/GVRRenderer.mm b/Samples/GVRKit/GVRRenderer.mm deleted file mode 100644 index 10aa648..0000000 --- a/Samples/GVRKit/GVRRenderer.mm +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRRenderer.h" - -static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000; - -// Exposes internal methods of GVRHeadPose. -@interface GVRHeadPose (GVRInternal) - -// Set the head pose transform, orientation and render size. -- (void)setHeadPose:(gvr::Mat4f &)headPose - renderSize:(gvr::Sizei)renderSize - orientation:(UIInterfaceOrientation)orientation - nextFrameTime:(NSTimeInterval)nextFrameTime; - -// Set the eye transform for a given eye and its viewport. -- (void)setEyePose:(gvr::Mat4f &)eyePose - forEye:(GVREye)eye - bufferViewport:(gvr::BufferViewport *)bufferViewport; - -// Add yaw and pitch rotation to the head pose. -- (void)addToHeadRotationYaw:(CGFloat)yaw andPitch:(CGFloat)pitch; - -// Remove all yaw and pitch rotations from the head pose. -- (void)resetHeadRotation; - -@end - -@interface GVRRenderer () { - std::unique_ptr _gvrApi; - std::unique_ptr _viewportList; - std::unique_ptr _swapchain; - gvr::Sizei _renderSize; - gvr::Sizei _size; - UIInterfaceOrientation _orientation; - GLKMatrix4 _headRotation; - GVRHeadPose *_headPose; -} -@end - -@implementation GVRRenderer - -- (void)initializeGl { - _gvrApi = gvr::GvrApi::Create(); - _gvrApi->InitializeGl(); - - std::vector specs; - specs.push_back(_gvrApi->CreateBufferSpec()); - _renderSize = specs[0].GetSize(); - _swapchain.reset(new gvr::SwapChain(_gvrApi->CreateSwapChain(specs))); - _viewportList.reset(new gvr::BufferViewportList(_gvrApi->CreateEmptyBufferViewportList())); - - _headPose = [[GVRHeadPose alloc] init]; - _headRotation = GLKMatrix4Identity; -} - -- (void)clearGl { - _viewportList.release(); - _swapchain.release(); - _gvrApi.release(); -} - -- (void)drawFrame:(NSTimeInterval)nextFrameTime { - gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; - - gvr::Mat4f gvr_head_pose = _gvrApi->GetHeadSpaceFromStartSpaceRotation(target_time); - [_headPose setHeadPose:gvr_head_pose - renderSize:(_VRModeEnabled ? _renderSize : _size) - orientation:_orientation - nextFrameTime:nextFrameTime]; - - [self update:_headPose]; - - if (!self.VRModeEnabled) { - // Draw head (center eye) for monoscopic rendering. - [self draw:_headPose]; - } else { - _viewportList->SetToRecommendedBufferViewports(); - - gvr::Frame frame = _swapchain->AcquireFrame(); - frame.BindBuffer(0); - - // Draw eyes. - gvr::BufferViewport viewport; - for (int eye = GVR_LEFT_EYE; eye <= GVR_RIGHT_EYE; eye++) { - _viewportList->GetBufferViewport(eye, &viewport); - - gvr::Mat4f eye_pose = _gvrApi->GetEyeFromHeadMatrix(static_cast(eye)); - - [_headPose setEyePose:eye_pose forEye:static_cast(eye) bufferViewport:&viewport]; - - [self draw:_headPose]; - } - - // Bind back to the default framebuffer. - frame.Unbind(); - frame.Submit(*_viewportList, gvr_head_pose); - } -} - -- (void)refresh { - if (_gvrApi) { - _gvrApi->RefreshViewerProfile(); - } -} - -- (void)addToHeadRotationYaw:(CGFloat)yaw andPitch:(CGFloat)pitch { - [_headPose addToHeadRotationYaw:yaw andPitch:pitch]; -} - -- (void)resetHeadRotation { - [_headPose resetHeadRotation]; - if (_gvrApi) { - gvr_reset_tracking(_gvrApi->GetContext()); - } -} - -- (void)setSize:(CGSize)size andOrientation:(UIInterfaceOrientation)orientation { - CGFloat scale = [GVRRenderer screenDpi]; - _size = {static_cast(size.width * scale), static_cast(size.height * scale)}; - - _orientation = orientation; -} - -- (void)pause:(BOOL)pause { - if (!_gvrApi) { - return; - } - - if (pause) { - _gvrApi->PauseTracking(); - } else { - _gvrApi->ResumeTracking(); - } -} - -- (BOOL)handleTrigger { - return [self handleTrigger:_headPose]; -} - -- (BOOL)handleTrigger:(GVRHeadPose *)headPose { - // Overridden by subclasses. - return NO; -} - -- (void)update:(GVRHeadPose *)headPose { - // Overridden by subclasses. -} - -- (void)draw:(GVRHeadPose *)headPose { - // Overridden by subclasses. -} - -#pragma mark - Private - -+ (CGFloat)screenDpi { - static dispatch_once_t onceToken; - static CGFloat scale; - dispatch_once(&onceToken, ^{ - if ([[UIScreen mainScreen] respondsToSelector:@selector(nativeScale)]) { - scale = [UIScreen mainScreen].nativeScale; - } else { - scale = [UIScreen mainScreen].scale; - } - }); - - return scale; -} - -@end diff --git a/Samples/GVRKit/GVRRendererView.h b/Samples/GVRKit/GVRRendererView.h deleted file mode 100644 index 5610ee7..0000000 --- a/Samples/GVRKit/GVRRendererView.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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 clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-modular-include-in-framework-module" -#import "GVROverlayView.h" -#pragma clang diagnostic pop -#import "GVRRenderer.h" - -/** - * Defines a view to handle GVR rendering. It provides its own render loop using |CADisplayLink|. It - * can be initialized with an instance of |GVRRenderer|. - */ -@interface GVRRendererView : GLKView - -/** Convenience initializer with the provided renderer. If another initializer is used, the - * renderer is initialized to |GVRSceneRenderer}. - * - * @param renderer The renderer used to render the contents of the view. - */ -- (instancetype)initWithRenderer:(GVRRenderer *)renderer; - -/** The renderer used to render the contents of the view. */ -@property(nonatomic, readonly) GVRRenderer *renderer; - -/** The overlay view used to provide a UI layer for Cardboard features such as icons to switch - * between monoscopic and stereoscopic rendering, a transition view to prompt the user to insert - * the phone is the viewer and to pair to a different viewer. */ -@property(nonatomic, readonly) GVROverlayView* overlayView; - -/** Allows toggling between monoscopic and stereoscopic (VR mode) rendering. */ -@property(nonatomic) BOOL VRModeEnabled; - -/** Pause or resume the |CADisplayLink| render loop. */ -@property(nonatomic) BOOL paused; - -@end diff --git a/Samples/GVRKit/GVRRendererView.mm b/Samples/GVRKit/GVRRendererView.mm deleted file mode 100644 index a3cc833..0000000 --- a/Samples/GVRKit/GVRRendererView.mm +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRRendererView.h" - -#import "GVRSceneRenderer.h" - -/** Defines a class to set the supplied EAGLContext and restore old context when destroyed. **/ -class GVRSetContext { -public: - GVRSetContext(EAGLContext *context) { - _oldContext = [EAGLContext currentContext]; - [EAGLContext setCurrentContext:context]; - } - ~GVRSetContext() { - [EAGLContext setCurrentContext:_oldContext]; - } -private: - EAGLContext *_oldContext; -}; - -@implementation GVRRendererView { - CADisplayLink *_displayLink; - BOOL _initialized; -} - -- (instancetype)init { - return [self initWithRenderer:nil]; -} - -- (instancetype)initWithRenderer:(GVRRenderer *)renderer { - if (self = [super init]) { - // Default to |GVRSceneRenderer| if no renderer is provided. - if (renderer == nil) { - renderer = [[GVRSceneRenderer alloc] init]; - } - _renderer = renderer; - - // Create an overlay view on top of the GLKView. - _overlayView = [[GVROverlayView alloc] initWithFrame:self.bounds]; - _overlayView.hidesBackButton = YES; - _overlayView.autoresizingMask = - UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self addSubview:_overlayView]; - - // Add a tap gesture to handle viewer trigger action. - UITapGestureRecognizer *tapGesture = - [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapGLView:)]; - [self addGestureRecognizer:tapGesture]; - - // Add pan gesture to allow manual tracking. - UIPanGestureRecognizer *panGesture = - [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPanGLView:)]; - [self addGestureRecognizer:panGesture]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; - self.drawableDepthFormat = GLKViewDrawableDepthFormat16; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationWillResignActive:) - name:UIApplicationWillResignActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - } - return self; -} - -- (void)dealloc { - // Shutdown GVRRenderer. - GVRSetContext context(self.context); - [_renderer clearGl]; - [self deleteDrawable]; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)setVRModeEnabled:(BOOL)VRModeEnabled { - if (_VRModeEnabled == VRModeEnabled) { - return; - } - - _renderer.VRModeEnabled = VRModeEnabled; - - [self willChangeValueForKey:@"VRModeEnabled"]; - _VRModeEnabled = VRModeEnabled; - [self didChangeValueForKey:@"VRModeEnabled"]; - - [self updateOverlayView]; -} - -- (void)setPaused:(BOOL)paused { - [self willChangeValueForKey:@"VRModeEnabled"]; - _paused = paused; - [self didChangeValueForKey:@"VRModeEnabled"]; - - [_renderer pause:paused]; - - _displayLink.paused = (self.superview == nil || _paused); -} - -- (void)didMoveToSuperview { - [super didMoveToSuperview]; - - // Start rendering only when added to a superview and vice versa. - if (self.superview) { - [self startRenderer]; - } else { - [self stopRenderer]; - } -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - if (!_initialized) { - _initialized = YES; - // Initialize GVRRenderer. - GVRSetContext context(self.context); - [self bindDrawable]; - [_renderer initializeGl]; - } - - UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; - [_renderer setSize:self.bounds.size andOrientation:orientation]; -} - -- (void)drawRect:(CGRect)rect { - [super drawRect:rect]; - - if (!_initialized) { - return; - } - - GVRSetContext context(self.context); - - if ([_displayLink respondsToSelector:@selector(targetTimestamp)]) { - [_renderer drawFrame:_displayLink.targetTimestamp]; - } else { - NSTimeInterval nextFrameTime = - _displayLink.timestamp + (_displayLink.duration * _displayLink.frameInterval); - [_renderer drawFrame:nextFrameTime]; - } -} - -#pragma mark - Actions - -- (void)didTapGLView:(UIPanGestureRecognizer *)panGesture { - GVRSetContext context(self.context); - // If renderer does not handle the trigger, call the delegate. - if ([_renderer handleTrigger]) { - return; - } - if ([self.overlayView.delegate respondsToSelector:@selector(didTapTriggerButton)]) { - [self.overlayView.delegate didTapTriggerButton]; - } -} - -- (void)didPanGLView:(UIPanGestureRecognizer *)panGesture { - CGPoint translation = [panGesture translationInView:self]; - [panGesture setTranslation:CGPointZero inView:self]; - - // Compute rotation from translation delta. - CGFloat yaw = GLKMathDegreesToRadians(-translation.x); - CGFloat pitch = GLKMathDegreesToRadians(-translation.y); - - [_renderer addToHeadRotationYaw:yaw andPitch:pitch]; -} - -#pragma mark - NSNotificationCenter - -- (void)applicationWillResignActive:(NSNotification *)notification { - self.paused = YES; -} - -- (void)applicationDidBecomeActive:(NSNotification *)notification { - self.paused = NO; -} - -#pragma mark - Private - -- (void)updateOverlayView { - // Transition view is always shown when VR mode is toggled ON. - _overlayView.hidesTransitionView = _overlayView.hidesTransitionView || !_VRModeEnabled; - _overlayView.hidesSettingsButton = !_VRModeEnabled; - _overlayView.hidesAlignmentMarker = !_VRModeEnabled; - _overlayView.hidesFullscreenButton = !_VRModeEnabled; - _overlayView.hidesCardboardButton = _VRModeEnabled; - - [_overlayView setNeedsLayout]; -} - -- (void)startRenderer { - if (!_displayLink) { - // Create a CADisplayLink instance to drive our render loop. - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(display)]; - if ([_displayLink respondsToSelector:@selector(preferredFramesPerSecond)]) { - _displayLink.preferredFramesPerSecond = 60; - } - - [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - _displayLink.paused = _paused; - } - - [self updateOverlayView]; -} - -- (void)stopRenderer { - // Invalidate CADisplayLink instance, which should release us. - [_displayLink invalidate]; - _displayLink = nil; -} - -@end diff --git a/Samples/GVRKit/GVRRendererViewController.h b/Samples/GVRKit/GVRRendererViewController.h deleted file mode 100644 index e903283..0000000 --- a/Samples/GVRKit/GVRRendererViewController.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRRendererView.h" - -/** - * @enum GVRDisplayMode - * - * Enumeration of the display modes, used to identify the |GVRRenderer| used for rendering. - */ -typedef NS_ENUM(NSInteger, GVRDisplayMode) { - kGVRDisplayModeEmbedded, - kGVRDisplayModeFullscreenMonoscopic, - kGVRDisplayModeFullscreenStereoscopic, -}; - -/** Defines a delegate used to provide an instance of |GVRRenderer| to the controller's view. */ -@protocol GVRRendererViewControllerDelegate - -- (GVRRenderer *)rendererForDisplayMode:(GVRDisplayMode)displayMode; - -@optional - -/** Handle user tapping the renderer view. */ -- (void)didTapTriggerButton; - -/** Return YES to hide the transition view. */ -- (BOOL)shouldHideTransitionView; - -@end - -/** - * Defines a view controller to host a |GVRRendererView|. This should be used for presenting - * fullscreen. It also handles interface orientation logic and interfacing with the overlay view - * during viewer pairing. This view controller is also recommended when embedding its view in - * another view controller's view. In that case, this view controller should be added as a child - * view controller to handle |viewWillAppear| and |viewWillDisappear| lifecycle events. - */ -@interface GVRRendererViewController : UIViewController - -/** A convenience initializer to be used with the supplied |GVRRenderer|. */ -- (instancetype)initWithRenderer:(GVRRenderer *)renderer; - -@property(nonatomic, weak) id delegate; - -@property(nonatomic, readonly) GVRRendererView *rendererView; - -@end diff --git a/Samples/GVRKit/GVRRendererViewController.m b/Samples/GVRKit/GVRRendererViewController.m deleted file mode 100644 index af4e0eb..0000000 --- a/Samples/GVRKit/GVRRendererViewController.m +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRRendererViewController.h" - -#import "GVRRendererView.h" - -@interface GVRRendererViewController () { - GVRRenderer *_renderer; -} - -@end - -@implementation GVRRendererViewController - -- (instancetype)initWithRenderer:(GVRRenderer *)renderer { - if (self = [super init]) { - _renderer = renderer; - } - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (GVRRendererView *)rendererView { - return (GVRRendererView *)self.view; -} - -- (void)loadView { - if (!_renderer && [self.delegate respondsToSelector:@selector(rendererForDisplayMode:)]) { - _renderer = [self.delegate rendererForDisplayMode:kGVRDisplayModeEmbedded]; - } - self.view = [[GVRRendererView alloc] initWithRenderer:_renderer]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // We need device orientation change notifications to work. - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; - }); - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didChangeOrientation:) - name:UIDeviceOrientationDidChangeNotification - object:nil]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - self.rendererView.paused = NO; - self.rendererView.overlayView.delegate = self; - - if (self.isModal) { - // Back button is always visible when presented. - self.rendererView.overlayView.hidesBackButton = NO; - } -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - self.rendererView.paused = YES; - - // Since our orientation is fixed to landscape right in modal state, upon returning from the modal - // state, reset the UI orientation to the device's orientation. - if (self.isModal) { - [UIViewController attemptRotationToDeviceOrientation]; - } -} - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations { - // GVR only supports landscape right orientation when the phone is inserted in the viewer. - if (self.isModal) { - return UIInterfaceOrientationMaskLandscapeRight; - } else { - return [super supportedInterfaceOrientations]; - } -} - -#pragma mark - GVROverlayViewDelegate - Works only when we are presented. - -- (void)didTapTriggerButton { - // In embedded mode, pass the trigger tap to our delegate. - if (self.isModal && [self.delegate respondsToSelector:@selector(didTapTriggerButton)]) { - [self.delegate didTapTriggerButton]; - } -} - -- (void)didTapBackButton { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -- (UIViewController *)presentingViewControllerForSettingsDialog { - return self; -} - -- (void)didPresentSettingsDialog:(BOOL)presented { - // The overlay view is presenting the settings dialog. Pause our rendering while presented. - self.rendererView.paused = presented; -} - -- (void)didChangeViewerProfile { - // Renderer's OnResume also refreshes viewer profile. - [_renderer refresh]; -} - -- (void)shouldDisableIdleTimer:(BOOL)shouldDisable { - [UIApplication sharedApplication].idleTimerDisabled = shouldDisable; -} - -- (void)didTapCardboardButton { - // Toggle VR mode if we are being presented. - if ([self isModal]) { - self.rendererView.VRModeEnabled = !self.rendererView.VRModeEnabled; - } else { - // We are in embedded mode, present another instance of GVRRendererViewController. - if ([self.delegate respondsToSelector:@selector(rendererForDisplayMode:)]) { - // Check if cardboard or fullscreen button was shown on the overlay view to determine - // VRModeEnabled flag. - BOOL VRModeEnabled = self.rendererView.overlayView.hidesFullscreenButton && - !self.rendererView.overlayView.hidesCardboardButton; - GVRDisplayMode displayMode = (VRModeEnabled ? kGVRDisplayModeFullscreenStereoscopic - : kGVRDisplayModeFullscreenMonoscopic); - GVRRenderer *renderer = [self.delegate rendererForDisplayMode:displayMode]; - - GVRRendererViewController *viewController = - [[GVRRendererViewController alloc] initWithRenderer:renderer]; - GVRRendererView *rendererView = viewController.rendererView; - - if ([self.delegate respondsToSelector:@selector(shouldHideTransitionView)]) { - rendererView.overlayView.hidesTransitionView = [self.delegate shouldHideTransitionView]; - } - - rendererView.VRModeEnabled = VRModeEnabled; - - [self.parentViewController presentViewController:viewController animated:YES completion:nil]; - } - } -} - -#pragma mark - NSNotificationCenter - -- (void)didChangeOrientation:(NSNotification *)notification { - // Request a layout change on the render view since iOS does not call layoutSubviews on 180-degree - // orientation changes. - [self.view setNeedsLayout]; -} - -#pragma mark - Private - -// Returns YES if this view controller is being presented. */ -- (BOOL)isModal { - if ([self presentingViewController]) { - return YES; - } - if ([[[self navigationController] presentingViewController] presentedViewController] == - [self navigationController]) { - return YES; - } - if ([[[self tabBarController] presentingViewController] - isKindOfClass:[UITabBarController class]]) { - return YES; - } - - return NO; -} - -@end diff --git a/Samples/GVRKit/GVRReticleRenderer.h b/Samples/GVRKit/GVRReticleRenderer.h deleted file mode 100644 index 6a9970e..0000000 --- a/Samples/GVRKit/GVRReticleRenderer.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRSceneRenderer.h" - -/** Defines a renderer for a reticle draw at the center for display. */ -@interface GVRReticleRenderer : NSObject - -/** The depth at which to draw the reticle. */ -@property(nonatomic) CGFloat depth; - -@end diff --git a/Samples/GVRKit/GVRReticleRenderer.mm b/Samples/GVRKit/GVRReticleRenderer.mm deleted file mode 100644 index 1690f52..0000000 --- a/Samples/GVRKit/GVRReticleRenderer.mm +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRReticleRenderer.h" - -// The reticle quad is 2 * SIZE units. -static const float kReticleSize = .01f; -static const float kReticleDistance = 0.3; -static const int kCoordsPerVertex = 3; -static const NSInteger kVertexStrideBytes = kCoordsPerVertex * sizeof(float); -static const float kVertexData[] = { - -kReticleSize, -kReticleSize, -kReticleDistance, - kReticleSize, -kReticleSize, -kReticleDistance, - -kReticleSize, kReticleSize, -kReticleDistance, - kReticleSize, kReticleSize, -kReticleDistance, -}; - -// Vertex shader implementation. -static const char *kVertexShaderString = R"( -uniform mat4 uMvpMatrix; -attribute vec3 aPosition; -varying vec2 vCoords; - -// Passthrough normalized vertex coordinates. -void main() { - gl_Position = uMvpMatrix * vec4(aPosition, 1); - vCoords = aPosition.xy / vec2(.01, .01); -} -)"; - -// Procedurally render a ring on the quad between the specified radii. -static const char *kPassThroughFragmentShaderString = R"( -precision mediump float; -varying vec2 vCoords; - -// Simple ring shader that is white between the radii and transparent elsewhere. -void main() { - float r = length(vCoords); - // Blend the edges of the ring at .55 +/- .05 and .85 +/- .05. - float alpha = smoothstep(0.5, 0.6, r) * (1.0 - smoothstep(0.8, 0.9, r)); - if (alpha == 0.0) { - discard; - } else { - gl_FragColor = vec4(alpha); - } -} -)"; - -@implementation GVRReticleRenderer { - GLuint _program; - GLint _positionAttrib; - GLint _mvpMatrix; - GLuint _vertex_buffer; -} - -- (instancetype)init { - if (self = [super init]) { - _depth = -0.3; - } - return self; -} - -@synthesize initialized; -@synthesize hidden; - -- (void)initializeGl { - // Load the vertex/fragment shaders. - const GLuint vertex_shader = loadShader(GL_VERTEX_SHADER, kVertexShaderString); - NSAssert(vertex_shader != 0, @"Failed to load vertex shader"); - const GLuint fragment_shader = - loadShader(GL_FRAGMENT_SHADER, kPassThroughFragmentShaderString); - NSAssert(fragment_shader != 0, @"Failed to load fragment shader"); - - _program = glCreateProgram(); - NSAssert(_program != 0, @"Failed to create program"); - glAttachShader(_program, vertex_shader); - glAttachShader(_program, fragment_shader); - - // Link the shader program. - glLinkProgram(_program); - NSAssert(checkProgramLinkStatus(_program), @"Failed to link _program"); - - // Get the location of our attributes so we can bind data to them later. - _positionAttrib = glGetAttribLocation(_program, "aPosition"); - NSAssert(_positionAttrib != -1, @"glGetAttribLocation failed for aPosition"); - _mvpMatrix = glGetUniformLocation(_program, "uMvpMatrix"); - NSAssert(_mvpMatrix != -1, @"Error fetching uniform values for shader."); - - glGenBuffers(1, &_vertex_buffer); - NSAssert(_vertex_buffer != 0, @"glGenBuffers failed for vertex buffer"); - glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData, GL_STATIC_DRAW); - - checkGLError("initialize"); - - initialized = YES; -} - -- (void)clearGl { - if (_vertex_buffer) { - GLuint buffers[] = {_vertex_buffer}; - glDeleteBuffers(1, buffers); - } - if (_program) { - glDeleteProgram(_program); - } - initialized = NO; -} - -- (void)update:(GVRHeadPose *)headPose { -} - -- (void)draw:(GVRHeadPose *)headPose { - glDisable(GL_DEPTH_TEST); - glClear(GL_DEPTH_BUFFER_BIT); - checkGLError("glClear"); - - // Configure shader. - glUseProgram(_program); - checkGLError("program"); - - GLKMatrix4 modelViewMatrix = headPose.eyeTransform; - modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0, 0, _depth); - GLKMatrix4 projection_matrix = [headPose projectionMatrixWithNear:0.1f far:100.0f]; - modelViewMatrix = GLKMatrix4Multiply(projection_matrix, modelViewMatrix); - - glUniformMatrix4fv(_mvpMatrix, 1, GL_FALSE, modelViewMatrix.m); - checkGLError("mvpMatrix"); - - // Render quad. - glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer); - glEnableVertexAttribArray(_positionAttrib); - glVertexAttribPointer( - _positionAttrib, kCoordsPerVertex, GL_FLOAT, GL_FALSE, kVertexStrideBytes, 0); - - checkGLError("vertex data"); - - int numVertices = sizeof(kVertexData) / sizeof(float) / kCoordsPerVertex; - glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices); - checkGLError("glDrawArrays"); - - glDisableVertexAttribArray(_positionAttrib); -} - -@end diff --git a/Samples/GVRKit/GVRSceneRenderer.h b/Samples/GVRKit/GVRSceneRenderer.h deleted file mode 100644 index 035f728..0000000 --- a/Samples/GVRKit/GVRSceneRenderer.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRRenderer.h" - -/** - * Defines an interface for a render object that is placed in a scene graph. - */ -@protocol GVRRenderObject - -/** - * Returns YES if the render object is initialized. This is useful when the - * object is moved around in the scene graph. - */ -@property(nonatomic, readonly) BOOL initialized; - -/** Allows hiding or showing the render object in the scene. */ -@property(nonatomic) BOOL hidden; - -/** Initializes GL resources needed for rendering the render object. */ -- (void)initializeGl; - -/** Renders the object given the head pose. */ -- (void)draw:(GVRHeadPose *)headPose; - -@optional -/** Releases the GL resources. */ -- (void)clearGl; - -/** Updates GL state needed before ::draw: is called. */ -- (void)update:(GVRHeadPose *)headPose; - -/** Pauses or resumes rendering. */ -- (void)pause:(BOOL)pause; - -/** - * Returns YES if render object handles the trigger button press. This stops - * render objects next in the display list from handling the trigger press. - */ -- (BOOL)handleTrigger:(GVRHeadPose *)headPose; -@end - - -/** - * Defines a simple list of render objects. Each item in the list implements the - * |GVRRenderObject| protocol, including GVRRenderList itself. This results in - * a scene graph data structure. Objects in the list are drawn in depth-first order. - */ -@interface GVRRenderList : NSObject -- (void)addRenderObject:(id)renderTarget; -- (void)insertRenderObject:(id)renderTarget atIndex:(NSUInteger)index; -- (void)removeRenderObject:(id)renderTarget; -- (void)removeRenderObjectAtIndex:(NSUInteger)index; -- (void)removeAll; -- (id)objectAtIndex:(NSUInteger)index; -- (NSUInteger)count; -@end - -/** Defines a scene renderer with a render list of |GVRRenderObject| objects. */ -@interface GVRSceneRenderer : GVRRenderer - -@property(nonatomic) GVRRenderList *renderList; - -@property(nonatomic) BOOL hidesReticle; - -@end - -// Helper methods used during OpenGL rendering. -void checkGLError(const char *label); -GLuint loadShader(GLenum type, const char *shader_src); -bool checkProgramLinkStatus(GLuint shader_program); - diff --git a/Samples/GVRKit/GVRSceneRenderer.mm b/Samples/GVRKit/GVRSceneRenderer.mm deleted file mode 100644 index 1d293bd..0000000 --- a/Samples/GVRKit/GVRSceneRenderer.mm +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRSceneRenderer.h" - -#import "GVRReticleRenderer.h" - -@implementation GVRSceneRenderer { - GVRReticleRenderer *_reticle; -} - -#pragma mark - GVRRenderer - -- (instancetype)init { - if (self = [super init]) { - _renderList = [[GVRRenderList alloc] init]; - _reticle = [[GVRReticleRenderer alloc] init]; - } - return self; -} - -- (void)initializeGl { - [super initializeGl]; - - [_renderList initializeGl]; - [_reticle initializeGl]; -} - -- (void)clearGl { - [super clearGl]; - - [_reticle clearGl]; - [_renderList clearGl]; -} - -- (void)update:(GVRHeadPose *)headPose { - checkGLError("pre update"); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glEnable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - checkGLError("update"); - - [_renderList update:headPose]; - - if (!self.hidesReticle) { - [_reticle update:headPose]; - } -} - -- (void)draw:(GVRHeadPose *)headPose { - CGRect viewport = [headPose viewport]; - glViewport(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height); - glScissor(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - checkGLError("glClear"); - - [_renderList draw:headPose]; - - if (!self.hidesReticle) { - [_reticle draw:headPose]; - } -} - -- (void)pause:(BOOL)pause { - [super pause:pause]; - - [_renderList pause:pause]; -} - -- (BOOL)handleTrigger:(GVRHeadPose *)headPose { - return [_renderList handleTrigger:headPose]; -} - -@end - -#pragma mark - GVRRenderList - -@implementation GVRRenderList { - NSMutableArray *_renderObjects; -} - -@synthesize initialized; -@synthesize hidden; - -- (instancetype)init { - if (self = [super init]) { - _renderObjects = [[NSMutableArray alloc] init]; - } - return self; -} - -- (void)addRenderObject:(id)renderTarget { - [_renderObjects addObject:renderTarget]; -} - -- (void)insertRenderObject:(id)renderTarget atIndex:(NSUInteger)index { - [_renderObjects insertObject:renderTarget atIndex:index]; -} - -- (void)removeRenderObject:(id)renderTarget { - [_renderObjects removeObject:renderTarget]; -} - -- (void)removeRenderObjectAtIndex:(NSUInteger)index { - [_renderObjects removeObjectAtIndex:index]; -} - -- (void)removeAll { - [_renderObjects removeAllObjects]; -} - -- (id)objectAtIndex:(NSUInteger)index { - return [_renderObjects objectAtIndex:index]; -} - -- (NSUInteger)count { - return _renderObjects.count; -} - -#pragma mark - GVRRenderObject - -- (void)initializeGl { - for (idtarget in _renderObjects) { - [target initializeGl]; - } - initialized = YES; -} - -- (void)clearGl { - for (idtarget in _renderObjects) { - if ([target respondsToSelector:@selector(clearGl)]) { - [target clearGl]; - } - } - initialized = NO; -} - -- (void)update:(GVRHeadPose *)headPose { - for (idtarget in _renderObjects) { - if (!target.initialized) { - [target initializeGl]; - } - if (!target.hidden && target.initialized && [target respondsToSelector:@selector(update:)]) { - [target update:headPose]; - } - } -} - -- (void)draw:(GVRHeadPose *)headPose { - for (idtarget in _renderObjects) { - if (!target.hidden && target.initialized) { - [target draw:headPose]; - } - } -} - -- (void)pause:(BOOL)pause { - for (idtarget in _renderObjects) { - if ([target respondsToSelector:@selector(pause:)]) { - [target pause:pause]; - } - } -} - -- (BOOL)handleTrigger:(GVRHeadPose *)headPose { - for (idtarget in _renderObjects) { - if ([target respondsToSelector:@selector(handleTrigger:)]) { - if ([target handleTrigger:headPose]) { - return YES; - } - } - } - return NO; -} - -@end - -#pragma mark - GL Helper methods - -void checkGLError(const char *label) { - int gl_error = glGetError(); - if (gl_error != GL_NO_ERROR) { - NSLog(@"GL error %s: %d", label, gl_error); - } - assert(glGetError() == GL_NO_ERROR); -} - -GLuint loadShader(GLenum type, const char *shader_src) { - GLint compiled = 0; - - // Create the shader object - const GLuint shader = glCreateShader(type); - if (shader == 0) { - return 0; - } - // Load the shader source - glShaderSource(shader, 1, &shader_src, NULL); - - // Compile the shader - glCompileShader(shader); - // Check the compile status - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - - if (!compiled) { - GLint info_len = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len); - - if (info_len > 1) { - char *info_log = ((char *)malloc(sizeof(char) * info_len)); - glGetShaderInfoLog(shader, info_len, NULL, info_log); - NSLog(@"Error compiling shader:%s", info_log); - free(info_log); - } - glDeleteShader(shader); - return 0; - } - return shader; -} - -// Checks the link status of the given program. -bool checkProgramLinkStatus(GLuint shader_program) { - GLint linked = 0; - glGetProgramiv(shader_program, GL_LINK_STATUS, &linked); - - if (!linked) { - GLint info_len = 0; - glGetProgramiv(shader_program, GL_INFO_LOG_LENGTH, &info_len); - - if (info_len > 1) { - char *info_log = ((char *)malloc(sizeof(char) * info_len)); - glGetProgramInfoLog(shader_program, info_len, NULL, info_log); - NSLog(@"Error linking program: %s", info_log); - free(info_log); - } - glDeleteProgram(shader_program); - return false; - } - return true; -} diff --git a/Samples/GVRKit/GVRTextureRenderer.h b/Samples/GVRKit/GVRTextureRenderer.h deleted file mode 100644 index 2450706..0000000 --- a/Samples/GVRKit/GVRTextureRenderer.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRSceneRenderer.h" - -/** Defines mesh type needed for rendering stereoscopic content. */ -typedef NS_ENUM(NSInteger, GVRMeshType) { - kGVRMeshTypeStereoLeftRight = 0, - kGVRMeshTypeStereoTopBottom, - kGVRMeshTypeMonoscopic -}; - -/** - * Defines a renderer for OpenGL textures. It supports rendering individual - * image textures and dual (Y + UV) video textures. These textures can be - * mapped to spherical or quad meshes. - */ -@interface GVRTextureRenderer : NSObject - -/** The position transform, in world space, where the texture will be placed. */ -@property(nonatomic) GLKMatrix4 position; - -/** The minimum bounding box vertex position. */ -@property(nonatomic, readonly) GLKVector3 aabbMin; - -/** The maximum bounding box vertex position. */ -@property(nonatomic, readonly) GLKVector3 aabbMax; - -/** - * Set spherical mesh for the texture. The mesh does not have be closed. - * - * @param radius Size of the sphere in meters. Must be > 0. - * @param latitudes Number of rows that make up the sphere. Must be >= 1. - * @param longitudes Number of columns that make up the sphere. Must be >= 1. - * @param verticalFov Total latitudinal degrees that are covered by the sphere. - * Must be in (0, 180]. - * @param horizontalFov Total longitudinal degrees that are covered by the - * sphere.Must be in (0, 360]. - * @param meshType The mesh type to use depending upon the media format. - */ -- (void)setSphericalMeshOfRadius:(CGFloat)radius - latitudes:(NSInteger)latitudes - longitudes:(NSInteger)longitudes - verticalFov:(NSInteger)verticalFov - horizontalFov:(NSInteger)horizontalFov - meshType:(GVRMeshType)meshType; - -/** - * Set a quad mesh with the given width and height. The unit for width and - * height is specified in meters. - * - * @param width The width in meters. - * @param height The height in meters. - * @param meshType The mesh type to use depending upon the media format. - * - * Use this to compute meters from pixels: - * 1 meter width at 1 meter depth = 2 * atan(0.5) = 53.13 degrees per meter. - * 15 pixels/degree * 53.13 degrees/meter = 796.951535313 pixels/meter. - */ -- (void)setQuadMeshOfWidth:(CGFloat)width - height:(CGFloat)height - meshType:(GVRMeshType)meshType; - -/** Sets the texture id for an image. See |GVRImageRenderer|. */ -- (void)setImageTextureId:(GLuint)textureId; - -/** - * Sets the textures for Y and UV of an individual video frame, along with the - * color conversion matrix. See |GVRVideoRenderer|. - */ -- (void)setVideoYTextureId:(GLuint)yTextureId - uvTextureId:(GLuint)uvTextureId - colorConversionMatrix:(GLKMatrix4)colorConversionMatrix; - -@end diff --git a/Samples/GVRKit/GVRTextureRenderer.mm b/Samples/GVRKit/GVRTextureRenderer.mm deleted file mode 100644 index fe12d65..0000000 --- a/Samples/GVRKit/GVRTextureRenderer.mm +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRTextureRenderer.h" - -// Constants related to vertex data. -static const NSInteger POSITION_COORDS_PER_VERTEX = 3; -// The vertex contains texture coordinates for both the left & right eyes. If the SCENE is -// rendered in VR, the appropriate part of the vertex would be selected at runtime. For mono -// SCENES, only the left eye's UV coordinates are used. -// For mono MEDIA, the UV coordinates are duplicated in each. For stereo MEDIA, the UV coords -// poNSInteger to the appropriate part of the source media. -static const NSInteger TEXTURE_COORDS_PER_VERTEX = 2 * 2; -static const NSInteger COORDS_PER_VERTEX = POSITION_COORDS_PER_VERTEX + TEXTURE_COORDS_PER_VERTEX; -static const NSInteger VERTEX_STRIDE_BYTES = COORDS_PER_VERTEX * sizeof(float); - -// Vertex shader implementation. -static const char *kVertexShaderString = R"( - #version 100 - - uniform mat4 uMvpMatrix; - attribute vec4 aPosition; - attribute vec2 aTexCoords; - varying vec2 vTexCoords; - void main(void) { - gl_Position = uMvpMatrix * aPosition; - vTexCoords = aTexCoords; - } -)"; - -// Simple pass-through texture fragment shader. -static const char *kPassThroughFragmentShaderString = R"( - - #ifdef GL_ES - precision mediump float; - #endif - uniform sampler2D uTexture; - varying vec2 vTexCoords; - - void main(void) { - gl_FragColor = texture2D(uTexture, vTexCoords); - } -)"; - -// Simple pass-through video fragment shader. -static const char *kPassThroughVideoFragmentShaderString = R"( - - #ifdef GL_ES - precision mediump float; - #endif - uniform sampler2D uTextureY; - uniform sampler2D uTextureUV; - uniform mat4 uColorConversionMatrix; - varying vec2 vTexCoords; - - void main(void) { - float u = vTexCoords.x; - float v = vTexCoords.y; - - vec3 yuv; - yuv.x = texture2D(uTextureY, vec2(u, v)).r; - yuv.yz = texture2D(uTextureUV, vec2(u, v)).rg; - gl_FragColor = uColorConversionMatrix * vec4(yuv, 1.0); - } -)"; - -@implementation GVRTextureRenderer { - BOOL _initialized; - BOOL _hidden; - BOOL _hasTextureId; - BOOL _isVideoTextureRenderer; - BOOL _flipTextureVertically; - BOOL _needsRebindVertexData; - NSData *_vertexData; - GLuint _textureId; - GLuint _yTextureId; - GLuint _uvTextureId; - GLKMatrix4 _colorConversionMatrix; - - GLuint _program; - GLint _positionAttrib; - GLint _texCoords; - GLint _mvpMatrix; - GLint _texture; - GLint _yTexture; - GLint _uvTexture; - GLint _colorMatrix; - GLuint _vertex_buffer; -} - -@synthesize initialized; -@synthesize hidden; - -- (instancetype)init { - if (self = [super init]) { - _position = GLKMatrix4Identity; - } - return self; -} - -- (void)setSphericalMeshOfRadius:(CGFloat)radius - latitudes:(NSInteger)latitudes - longitudes:(NSInteger)longitudes - verticalFov:(NSInteger)verticalFov - horizontalFov:(NSInteger)horizontalFov - meshType:(GVRMeshType)meshType { - _vertexData = [GVRTextureRenderer makeSphereWithRadius:radius - latitudes:latitudes - longitudes:longitudes - verticalFov:verticalFov - horizontalFov:horizontalFov - meshType:meshType]; - [self computeAabbFromVertexData:_vertexData]; - _needsRebindVertexData = YES; -} - -- (void)setQuadMeshOfWidth:(CGFloat)width height:(CGFloat)height meshType:(GVRMeshType)meshType { - _vertexData = [GVRTextureRenderer makeQuadWithWidth:width height:height meshType:meshType]; - [self computeAabbFromVertexData:_vertexData]; - _needsRebindVertexData = YES; -} - -- (void)setIsVideoTextureRenderer:(BOOL)isVideoTextureRenderer { - _isVideoTextureRenderer = YES; -} - -- (void)setFlipTextureVertically:(BOOL)flipTextureVertically { - _flipTextureVertically = flipTextureVertically; -} - -- (void)setImageTextureId:(GLuint)textureId { - _hasTextureId = YES; - _textureId = textureId; -} - -- (void)setVideoYTextureId:(GLuint)yTextureId - uvTextureId:(GLuint)uvTextureId - colorConversionMatrix:(GLKMatrix4)colorConversionMatrix { - _hasTextureId = YES; - _yTextureId = yTextureId; - _uvTextureId = uvTextureId; - _colorConversionMatrix = colorConversionMatrix; -} - -- (void)initializeGl { - // Load the vertex/fragment shaders. - const GLuint vertex_shader = loadShader(GL_VERTEX_SHADER, kVertexShaderString); - NSAssert(vertex_shader != 0, @"Failed to load vertex shader"); - const GLuint fragment_shader = - loadShader(GL_FRAGMENT_SHADER, - _isVideoTextureRenderer ? kPassThroughVideoFragmentShaderString - : kPassThroughFragmentShaderString); - NSAssert(fragment_shader != 0, @"Failed to load fragment shader"); - - _program = glCreateProgram(); - NSAssert(_program != 0, @"Failed to create program"); - glAttachShader(_program, vertex_shader); - glAttachShader(_program, fragment_shader); - - // Link the shader program. - glLinkProgram(_program); - NSAssert(checkProgramLinkStatus(_program), @"Failed to link _program"); - - // Get the location of our attributes so we can bind data to them later. - _positionAttrib = glGetAttribLocation(_program, "aPosition"); - NSAssert(_positionAttrib != -1, @"glGetAttribLocation failed for aPosition"); - _texCoords = glGetAttribLocation(_program, "aTexCoords"); - NSAssert(_texCoords != -1, @"glGetAttribLocation failed for aTexCoords"); - _mvpMatrix = glGetUniformLocation(_program, "uMvpMatrix"); - if (_isVideoTextureRenderer) { - _yTexture = glGetUniformLocation(_program, "uTextureY"); - _uvTexture = glGetUniformLocation(_program, "uTextureUV"); - _colorMatrix = glGetUniformLocation(_program, "uColorConversionMatrix"); - NSAssert(_mvpMatrix != -1 && _yTexture != -1 && _uvTexture != -1 && _colorMatrix != -1, - @"Error fetching uniform values for shader."); - } else { - _texture = glGetUniformLocation(_program, "uTexture"); - NSAssert(_mvpMatrix != -1 && _texture != -1, @"Error fetching uniform values for shader."); - } - - checkGLError("initialize"); - - initialized = YES; -} - -- (void)clearGl { - if (_vertex_buffer) { - GLuint buffers[] = {_vertex_buffer}; - glDeleteBuffers(1, buffers); - _vertex_buffer = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - if (_hasTextureId) { - _hasTextureId = NO; - if (_isVideoTextureRenderer) { - GLuint textures[] = {_yTextureId, _uvTextureId}; - glDeleteTextures(2, textures); - } else { - GLuint textures[] = {_textureId}; - glDeleteTextures(1, textures); - } - } - initialized = NO; -} - -- (void)update:(GVRHeadPose *)headPose { - if (_needsRebindVertexData) { - _needsRebindVertexData = NO; - - if (_vertex_buffer) { - GLuint buffers[] = {_vertex_buffer}; - glDeleteBuffers(1, buffers); - _vertex_buffer = 0; - } - } - if (_vertex_buffer == 0) { - glGenBuffers(1, &_vertex_buffer); - NSAssert(_vertex_buffer != 0, @"glGenBuffers failed for vertex buffer"); - glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, _vertexData.length, _vertexData.bytes, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } -} - -- (void)draw:(GVRHeadPose *)headPose { - if (!_hasTextureId) { - return; - } - - GLKMatrix4 modelMatrix = _position; - if (_flipTextureVertically) { - modelMatrix = GLKMatrix4Scale(modelMatrix, 1, -1, 1); - } - GLKMatrix4 viewMatrix = headPose.viewTransform; - GLKMatrix4 projectionMatrix = [headPose projectionMatrixWithNear:0.1f far:100.0f]; - - GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, viewMatrix); - modelViewProjectionMatrix = GLKMatrix4Multiply(modelViewProjectionMatrix, modelMatrix); - - // Select our shader. - glUseProgram(_program); - checkGLError("glUseProgram"); - - glUniformMatrix4fv(_mvpMatrix, 1, GL_FALSE, modelViewProjectionMatrix.m); - if (_isVideoTextureRenderer) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, _yTextureId); - glUniform1i(_yTexture, 0); - - checkGLError("bind video texture 0"); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _uvTextureId); - glUniform1i(_uvTexture, 1); - - checkGLError("bind video texture 1"); - - glUniformMatrix4fv(_colorMatrix, 1, GL_FALSE, _colorConversionMatrix.m); - - checkGLError("color matrix"); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, _textureId); - glUniform1i(_texture, 0); - checkGLError("bind texture"); - } - - glEnableVertexAttribArray(_positionAttrib); - glEnableVertexAttribArray(_texCoords); - checkGLError("enable vertex attribs"); - - // Load position data. - glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer); - glVertexAttribPointer( - _positionAttrib, POSITION_COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, VERTEX_STRIDE_BYTES, 0); - checkGLError("vertex position"); - - // Load texture data. - int textureOffset = - (headPose.eye == kGVRRightEye) ? POSITION_COORDS_PER_VERTEX + 2 : POSITION_COORDS_PER_VERTEX; - glVertexAttribPointer(_texCoords, - TEXTURE_COORDS_PER_VERTEX, - GL_FLOAT, - GL_FALSE, - VERTEX_STRIDE_BYTES, - (void *)(textureOffset * sizeof(float))); - checkGLError("texture offset"); - - // Render. - GLsizei numVertices = (GLsizei)(_vertexData.length / sizeof(float)) / COORDS_PER_VERTEX; - glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices); - checkGLError("glDrawArrays"); - - // Clear state. - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisableVertexAttribArray(_positionAttrib); - glDisableVertexAttribArray(_texCoords); - checkGLError("done drawing"); -} - -#pragma mark - Private - -- (void)computeAabbFromVertexData:(NSData *)vertexData { - for (int i = 0; i < vertexData.length; i = i + (sizeof(float) * COORDS_PER_VERTEX)) { - float *pos = (float *)vertexData.bytes + i / sizeof(float); - GLKVector3 v = GLKVector3Make(*(pos), *(pos + 1), *(pos + 2)); - _aabbMin = GLKVector3Minimum(_aabbMin, v); - _aabbMax = GLKVector3Maximum(_aabbMax, v); - } -} - -+ (NSData *)makeSphereWithRadius:(CGFloat)radius - latitudes:(NSInteger)latitudes - longitudes:(NSInteger)longitudes - verticalFov:(NSInteger)verticalFov - horizontalFov:(NSInteger)horizontalFov - meshType:(GVRMeshType)meshType { - // Compute angular size of each UV quad. - float verticalFovRads = GLKMathDegreesToRadians(verticalFov); - float horizontalFovRads = GLKMathDegreesToRadians(horizontalFov); - float quadHeightRads = verticalFovRads / latitudes; - float quadWidthRads = horizontalFovRads / longitudes; - NSInteger vertexCount = (2 * (longitudes + 1) + 2) * latitudes; - - NSInteger CPV = COORDS_PER_VERTEX; - float vertexData[vertexCount * CPV]; - - // Generate the data for the sphere which is a set of triangle strips representing each - // latitude band. - NSInteger v = 0; // Index into the vertex array. - // (i, j) represents a quad in the equirectangular sphere. - for (NSInteger j = 0; j < latitudes; ++j) { - // Each latitude band lies between the two phi values. Each vertical edge on a band lies on - // a theta value. - float phiLow = (quadHeightRads * j - verticalFovRads / 2.0f); - float phiHigh = (quadHeightRads * (j + 1) - verticalFovRads / 2.0f); - for (NSInteger i = 0; i < longitudes + 1; ++i) { // For each vertical edge in the band. - for (NSInteger k = 0; k < 2; ++k) { // For low and high points on an edge. - // For each point, determine it's angular position. - float phi = (k == 0) ? phiLow : phiHigh; - float theta = quadWidthRads * i + (float)M_PI - horizontalFovRads / 2.0f; - - // Set vertex position data. - vertexData[CPV * v + 0] = -(float)(radius * sin(theta) * cos(phi)); - vertexData[CPV * v + 1] = (float)(radius * sin(phi)); - vertexData[CPV * v + 2] = (float)(radius * cos(theta) * cos(phi)); - - // Set vertex texture.x data. - if (meshType == kGVRMeshTypeStereoLeftRight) { - vertexData[CPV * v + 3] = (i * quadWidthRads / horizontalFovRads) / 2.0f; - vertexData[CPV * v + 5] = (i * quadWidthRads / horizontalFovRads) / 2.0f + .5f; - } else { - vertexData[CPV * v + 3] = i * quadWidthRads / horizontalFovRads; - vertexData[CPV * v + 5] = i * quadWidthRads / horizontalFovRads; - } - - // Set vertex texture.y data. The "1 - ..." is due to Canvas vs GL coords. - if (meshType == kGVRMeshTypeStereoTopBottom) { - vertexData[CPV * v + 4] = 1 - (((j + k) * quadHeightRads / verticalFovRads) / 2.0f + .5f); - vertexData[CPV * v + 6] = 1 - ((j + k) * quadHeightRads / verticalFovRads) / 2.0f; - } else { - vertexData[CPV * v + 4] = 1 - (j + k) * quadHeightRads / verticalFovRads; - vertexData[CPV * v + 6] = 1 - (j + k) * quadHeightRads / verticalFovRads; - } - v++; - - // Break up the triangle strip using degenerate vertices by copying first and last points. - if ((i == 0 && k == 0) || (i == longitudes && k == 1)) { - // System.arraycopy(vertexData, CPV * (v - 1), vertexData, CPV * v, CPV); - memcpy(vertexData + (CPV * v), vertexData + (CPV * (v - 1)), CPV * sizeof(float)); - v++; - } - } - // Move on to the next vertical edge in the triangle strip. - } - // Move on to the next triangle strip. - } - - return [NSData dataWithBytes:vertexData length:sizeof(vertexData)]; -} - -+ (NSData *)makeQuadWithWidth:(CGFloat)width height:(CGFloat)height meshType:(GVRMeshType)meshType { - NSData *data = nil; - float w = (float)width; - float h = (float)height; - - switch (meshType) { - case kGVRMeshTypeStereoLeftRight: { - float vertices[] = {-w / 2, -h / 2, 0, 0, 1, .5f, 1, w, -h / 2, 0, .5f, 1, 1, 1, - -w / 2, h, 0, 0, 0, .5f, 0, w, h, 0, .5f, 0, 1, 0}; - data = [NSData dataWithBytes:vertices length:sizeof(vertices)]; - } break; - - case kGVRMeshTypeStereoTopBottom: { - float vertices[] = {-w / 2, -h / 2, 0, 0, .5f, 0, 1, w, -h / 2, 0, 1, .5f, 1, 1, - -w / 2, h, 0, 0, 0, 0, .5f, w, h, 0, 1, 0, 1, .5f}; - data = [NSData dataWithBytes:vertices length:sizeof(vertices)]; - } break; - - case kGVRMeshTypeMonoscopic: - default: { - float vertices[] = {-w / 2, -h / 2, 0, 0, 1, 0, 1, w, -h / 2, 0, 1, 1, 1, 1, - -w / 2, h, 0, 0, 0, 0, 0, w, h, 0, 1, 0, 1, 0}; - data = [NSData dataWithBytes:vertices length:sizeof(vertices)]; - } break; - } - return data; -} - -@end diff --git a/Samples/GVRKit/GVRUIViewRenderer.h b/Samples/GVRKit/GVRUIViewRenderer.h deleted file mode 100644 index c49cc54..0000000 --- a/Samples/GVRKit/GVRUIViewRenderer.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRTextureRenderer.h" - -/** Defines a texture renderer for UIView renderer to pixel buffers. */ -@interface GVRUIViewRenderer : GVRTextureRenderer - -/** Initializes with the given view. */ -- (instancetype)initWithView:(UIView *)view; - -@property(nonatomic) UIView *view; - -@end diff --git a/Samples/GVRKit/GVRUIViewRenderer.mm b/Samples/GVRKit/GVRUIViewRenderer.mm deleted file mode 100644 index 5bbd71f..0000000 --- a/Samples/GVRKit/GVRUIViewRenderer.mm +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRUIViewRenderer.h" - -#include - -// 1 meter width at 1 meter depth = 2 * atan(0.5) = 53.13 degrees per meter. -// 15 pixels per degree * 53.13 degrees per meter = 796.951535313 pixels per meter. -static const CGFloat kPixelsPerMeter = 796.951535313f; -static constexpr float kDefaultEpsilon = 1.0e-5f; - -@interface GVRTextureRenderer (Subclassing) -- (void)setFlipTextureVertically:(BOOL)flipTextureVertically; -@end - -@implementation GVRUIViewRenderer { - UIView *_view; - CVPixelBufferRef _pixelBuffer; - CVOpenGLESTextureRef _texture; - CVOpenGLESTextureCacheRef _textureCache; - CGPoint _hitTestPoint; -} - -- (instancetype)initWithView:(UIView *)view { - if (self = [super init]) { - super.flipTextureVertically = YES; - - _view = view; - } - return self; -} - -- (void)dealloc { - [self cleanUpTextures]; - [self clearGl]; -} - -- (void)setView:(UIView *)view { - [self willChangeValueForKey:@"view"]; - _view = view; - [self didChangeValueForKey:@"view"]; -} - -#pragma mark - GVRTextureRenderer - -- (void)initializeGl { - [super initializeGl]; - - if (self.initialized) { - // Create texture cache. - CVReturn status = CVOpenGLESTextureCacheCreate( - kCFAllocatorDefault, NULL, [EAGLContext currentContext], NULL, &_textureCache); - NSAssert(status == noErr, @"Error at CVOpenGLESTextureCacheCreate %d", status); - } -} - -- (void)clearGl { - [super clearGl]; - - if (_pixelBuffer) { - CVPixelBufferRelease(_pixelBuffer); - _pixelBuffer = NULL; - } - if (_textureCache) { - CFRelease(_textureCache); - _textureCache = NULL; - } -} - -- (void)update:(GVRHeadPose *)headPose { - // We should have a non-empty view to render. - if (!_view || CGRectIsEmpty(_view.bounds)) { - // Cleanup previous textures. - [self cleanUpTextures]; - return; - } - - // Create a pixel buffer to render the UIView if it does not exist or view's size has changed. - if (!_pixelBuffer || CVPixelBufferGetWidth(_pixelBuffer) != _view.bounds.size.width || - CVPixelBufferGetHeight(_pixelBuffer) != _view.bounds.size.height) { - // De-allocate previous pixel buffer. - if (_pixelBuffer) { - CVPixelBufferRelease(_pixelBuffer); - } - - // Set the mesh from the view size. - [self setMeshFromSize:_view.bounds.size]; - - // Now create the pixel buffer. - NSDictionary *options = @{ - (id)kCVPixelBufferIOSurfacePropertiesKey : @{}, - (id)kCVPixelBufferOpenGLCompatibilityKey : @(YES), - (id)kCVPixelBufferOpenGLESTextureCacheCompatibilityKey : @(YES) - }; - CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, - (int)_view.bounds.size.width, - (int)_view.bounds.size.height, - kCVPixelFormatType_32BGRA, - (__bridge CFDictionaryRef)options, - &_pixelBuffer); - NSAssert(status == kCVReturnSuccess, @"Error allocating pixel buffer %d", status); - } - - CVReturn status = CVPixelBufferLockBaseAddress(_pixelBuffer, 0); - NSAssert(status == kCVReturnSuccess, @"Error locking pixel buffer %d", status); - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - NSAssert(colorSpace != NULL, @"Error creating color space"); - - CGContextRef context = CGBitmapContextCreate(CVPixelBufferGetBaseAddress(_pixelBuffer), - CVPixelBufferGetWidth(_pixelBuffer), - CVPixelBufferGetHeight(_pixelBuffer), - 8, - CVPixelBufferGetBytesPerRow(_pixelBuffer), - colorSpace, - kCGImageAlphaPremultipliedLast); - CGColorSpaceRelease(colorSpace); - NSAssert(context != NULL, @"Error creating bitmap context."); - - // Draw the view to the pixel buffer. - [_view.layer renderInContext:context]; - - CGContextRelease(context); - CVPixelBufferUnlockBaseAddress(_pixelBuffer, 0); - - // Cleanup previous textures. - [self cleanUpTextures]; - - // Create a texture from the pixel buffer. - status = CVOpenGLESTextureCacheCreateTextureFromImage( - kCFAllocatorDefault, // The CFAllocatorRef to use for allocating the texture object. - _textureCache, // The texture cache object that will manage the texture. - _pixelBuffer, // The CVImageBufferRef that you want to create a texture from. - NULL, // A CFDictionaryRef for creating the CVOpenGLESTextureRef objects. - GL_TEXTURE_2D, // The target texture. Can be GL_TEXTURE_2D or GL_RENDERBUFFER. - GL_RGBA, // The number of color components in the texture. - (GLsizei)CVPixelBufferGetWidth(_pixelBuffer), // The width of the texture image. - (GLsizei)CVPixelBufferGetHeight(_pixelBuffer), // The height of the texture image. - GL_RGBA, // The format of the pixel data. - GL_UNSIGNED_BYTE, // The data type of the pixel data. - 0, // The plane of the CVImageBufferRef to map bind. - &_texture); // Where the newly created texture object will be placed. - - if (status == kCVReturnSuccess) { - [self setImageTextureId:CVOpenGLESTextureGetName(_texture)]; - } - - // Perform hittest for hover animations. - // if (_view.userInteractionEnabled) { - // [self hitTest:headPose]; - //} - - [super update:headPose]; -} - -- (BOOL)handleTrigger:(GVRHeadPose *)headPose { - if (_view.userInteractionEnabled && [self hitTest:headPose]) { - UIView *subview = [_view hitTest:_hitTestPoint withEvent:nil]; - if ([subview respondsToSelector:@selector(sendActionsForControlEvents:)]) { - [(UIControl *)subview sendActionsForControlEvents:UIControlEventTouchUpInside]; - return YES; - } - } - return NO; -} - -#pragma mark - Private - -- (void)setMeshFromSize:(CGSize)size { - CGFloat width = size.width / kPixelsPerMeter; - CGFloat height = size.height / kPixelsPerMeter; - - [self setQuadMeshOfWidth:width height:height meshType:kGVRMeshTypeMonoscopic]; -} - -- (void)cleanUpTextures { - if (_texture) { - CFRelease(_texture); - _texture = NULL; - } - - if (_textureCache) { - CVOpenGLESTextureCacheFlush(_textureCache, 0); - } -} - -- (BOOL)hitTest:(GVRHeadPose *)headPose { - _hitTestPoint.x = nan(NULL); - _hitTestPoint.y = nan(NULL); - - GLKQuaternion headRotation = - GLKQuaternionMakeWithMatrix4(GLKMatrix4Transpose([headPose headTransform])); - - GLKVector3 cameraOrigin = GLKVector3Make(0.0f, 0.0f, 0.0f); - GLKVector3 cameraDirection = GLKQuaternionRotateVector3(headRotation, GLKVector3Make(0, 0, -1)); - cameraDirection = GLKVector3Normalize(cameraDirection); - - // Transform camera "ray" to our model space. - GLKMatrix4 modelSpace = GLKMatrix4Invert(self.position, nil); - GLKVector3 modelOrigin = GLKMatrix4MultiplyVector3WithTranslation(modelSpace, cameraOrigin); - GLKVector3 modelDirection = GLKMatrix4MultiplyVector3(modelSpace, cameraDirection); - - // If the ray is negative or only barely positive, then the ray is pointing away from the plane. - if (fabs(modelDirection.v[2]) < kDefaultEpsilon) { - return NO; - } - - // If bounding box is zero, the intersection point is 0,0. - GLKVector3 aabbDiff = GLKVector3Subtract(self.aabbMax, self.aabbMin); - if (GLKVector3Length(aabbDiff) < kDefaultEpsilon) { - return NO; - } - - const float lambda = -modelOrigin.v[2] / modelDirection.v[2]; - GLKVector3 delta = GLKVector3Add(modelOrigin, GLKVector3MultiplyScalar(modelDirection, lambda)); - GLKVector3 relativeDelta = - GLKVector3Divide(GLKVector3Subtract(delta, self.aabbMin), aabbDiff); - CGPoint intersection = CGPointMake(relativeDelta.v[0], relativeDelta.v[1]); - - intersection.y += -self.aabbMax.v[1] / aabbDiff.v[1]; - intersection.y *= -1; - - intersection.x *= _view.bounds.size.width; - intersection.y *= _view.bounds.size.height; - - if (intersection.x >= 0 && intersection.x < _view.bounds.size.width && - intersection.y >= 0 && intersection.y < _view.bounds.size.height) { - _hitTestPoint = intersection; - return YES; - } - - return NO; -} - - -@end diff --git a/Samples/GVRKit/GVRVideoRenderer.h b/Samples/GVRKit/GVRVideoRenderer.h deleted file mode 100644 index 8cd8357..0000000 --- a/Samples/GVRKit/GVRVideoRenderer.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRTextureRenderer.h" - -#import - -/** Defines a texture renderer for video frames. */ -@interface GVRVideoRenderer : GVRTextureRenderer - -/** The AVPlayer instance to grab video frames from. */ -@property(nonatomic) AVPlayer *player; - -@end diff --git a/Samples/GVRKit/GVRVideoRenderer.mm b/Samples/GVRKit/GVRVideoRenderer.mm deleted file mode 100644 index bd02f25..0000000 --- a/Samples/GVRKit/GVRVideoRenderer.mm +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2017 Google Inc. All Rights Reserved. - * - * 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. - */ - -#import "GVRVideoRenderer.h" - -#include -#include - -// Studio swing implies: -// Y values are in the range [16, 235]; -// Cb and Cr are [16, 240]. -// (see e.g. BT.601 Annex 1, Table 3, Row 8; BT.709 Section 4 ('Digital representation') Row 4.6) -// -// In OpenGL RGB land, all three channels are [0, 255]. -// -// The matrices below handle the necessary scale, origin and axis adjustments necessary to translate -// from the BT colour spaces to RGB. - -// BT.601 colorspace, studio swing. -static const GLKMatrix4 kColorConversionMatrix601 = { - 1.164, 1.164, 1.164, 0.0, 0.0, -0.392, 2.017, 0.0, // NOLINT - 1.596, -0.813, 0.0, 0.0, -0.874165, 0.531828, -1.08549, 1.0}; // NOLINT - -// BT.709 colorspace, studio swing. -static const GLKMatrix4 kColorConversionMatrix709 = { - 1.164, 1.164, 1.164, 0.0, 0.0, -0.213, 2.112, 0.0, // NOLINT - 1.793, -0.533, 0, 0.0, -0.973051, 0.301427, -1.13318, 1.0}; // NOLINT - -@interface GVRTextureRenderer (Subclassing) -- (void)setIsVideoTextureRenderer:(BOOL)isVideoTextureRenderer; -@end - -@implementation GVRVideoRenderer { - AVPlayer *_player; - AVPlayerItemVideoOutput *_videoOutput; - - CVOpenGLESTextureRef _lumaTexture; - CVOpenGLESTextureRef _chromaTexture; - CVOpenGLESTextureCacheRef _videoTextureCache; -} - -- (void)dealloc { - [_player.currentItem removeOutput:_videoOutput]; - [_player removeObserver:self forKeyPath:@"status"]; -} - -- (void)setPlayer:(AVPlayer *)player { - // Remove KVO from previous player. - [_player.currentItem removeOutput:_videoOutput]; - [_player removeObserver:self forKeyPath:@"status"]; - - _player = player; - - // Create a pixel buffer to hold AVPlayerItemVideoOutput. - NSDictionary *attributes = - @{(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)}; - _videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:attributes]; - - // Observe player's status property. - [_player addObserver:self forKeyPath:@"status" options:0 context:nil]; - if (_player.status == AVPlayerStatusReadyToPlay) { - [_player.currentItem addOutput:_videoOutput]; - } -} - -#pragma mark - Private - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - if (object == _player && [keyPath isEqualToString:@"status"]) { - if (_player.status == AVPlayerStatusReadyToPlay) { - if (![_player.currentItem.outputs containsObject:_videoOutput]) { - [_player.currentItem addOutput:_videoOutput]; - } - } - } -} - -#pragma mark - GVRTextureRenderer - -- (void)initializeGl { - super.isVideoTextureRenderer = YES; - [super initializeGl]; - - // Create texture cache. - CVReturn err = CVOpenGLESTextureCacheCreate( - kCFAllocatorDefault, NULL, [EAGLContext currentContext], NULL, &_videoTextureCache); - NSAssert(err == noErr, @"Error at CVOpenGLESTextureCacheCreate %d", err); -} - -- (void)clearGl { - [super clearGl]; - - [self cleanUpTextures]; - if (_videoTextureCache) { - CFRelease(_videoTextureCache); - _videoTextureCache = NULL; - } -} - -- (void)update:(GVRHeadPose *)headPose { - CMTime itemTime = [_videoOutput itemTimeForHostTime:headPose.nextFrameTime]; - - if ([_videoOutput hasNewPixelBufferForItemTime:itemTime]) { - CVPixelBufferRef pixelBuffer = - [_videoOutput copyPixelBufferForItemTime:itemTime itemTimeForDisplay:NULL]; - if (pixelBuffer) { - [self cleanUpTextures]; - int videoWidth = (int)CVPixelBufferGetWidth(pixelBuffer); - int videoHeight = (int)CVPixelBufferGetHeight(pixelBuffer); - BOOL requiresChannelSizes = EAGLContext.currentContext.API > kEAGLRenderingAPIOpenGLES2; - - // Create Y and UV textures from the pixel buffer. RGB is not supported. - _lumaTexture = [self createSourceTexture:pixelBuffer - index:0 - format:requiresChannelSizes ? GL_RED : GL_RED_EXT - internalFormat:requiresChannelSizes ? GL_R8 : GL_RED_EXT - width:videoWidth - height:videoHeight]; - // UV-plane. - _chromaTexture = [self createSourceTexture:pixelBuffer - index:1 - format:requiresChannelSizes ? GL_RG : GL_RG_EXT - internalFormat:requiresChannelSizes ? GL_RG8 : GL_RG_EXT - width:(videoWidth + 1) / 2 - height:(videoHeight + 1) / 2]; - - // Use the color attachment to determine the appropriate color conversion matrix. - CFTypeRef colorAttachments = - CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL); - GLKMatrix4 colorConversionMatrix = - CFEqual(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4) - ? kColorConversionMatrix601 - : kColorConversionMatrix709; - - GLuint lumaTextureId = CVOpenGLESTextureGetName(_lumaTexture); - GLuint chromaTextureId = CVOpenGLESTextureGetName(_chromaTexture); - [self setVideoYTextureId:lumaTextureId - uvTextureId:chromaTextureId - colorConversionMatrix:colorConversionMatrix]; - - CFRelease(pixelBuffer); - pixelBuffer = 0; - } - } - [super update:headPose]; -} - -- (CVOpenGLESTextureRef)createSourceTexture:(CVPixelBufferRef)pixelBuffer - index:(int)index - format:(GLint)format - internalFormat:(GLint)internalFormat - width:(int)width - height:(int)height { - CVOpenGLESTextureRef texture; - CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage( - kCFAllocatorDefault, // The CFAllocatorRef to use for allocating the texture object. - _videoTextureCache, // The texture cache object that will manage the texture. - pixelBuffer, // The CVImageBufferRef that you want to create a texture from. - NULL, // A CFDictionaryRef for creating the CVOpenGLESTextureRef objects. - GL_TEXTURE_2D, // The target texture. Can be GL_TEXTURE_2D or GL_RENDERBUFFER. - internalFormat, // The number of color components in the texture. - width, // The width of the texture image. - height, // The height of the texture image. - format, // The format of the pixel data. - GL_UNSIGNED_BYTE, // The data type of the pixel data. - index, // The plane of the CVImageBufferRef to map bind. - &texture); // Where the newly created texture object will be placed. - - if (err) { - NSLog(@"Could not create Texture, err = %d", err); - return NULL; - } - - glBindTexture(CVOpenGLESTextureGetTarget(texture), CVOpenGLESTextureGetName(texture)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - return texture; -} - -- (void)cleanUpTextures { - if (_lumaTexture) { - CFRelease(_lumaTexture); - _lumaTexture = NULL; - } - - if (_chromaTexture) { - CFRelease(_chromaTexture); - _chromaTexture = NULL; - } - - if (_videoTextureCache) { - CVOpenGLESTextureCacheFlush(_videoTextureCache, 0); - } -} - -@end diff --git a/Samples/TreasureHunt/Podfile b/Samples/TreasureHunt/Podfile index ee2deed..0f07f2f 100644 --- a/Samples/TreasureHunt/Podfile +++ b/Samples/TreasureHunt/Podfile @@ -1,3 +1,4 @@ target 'TreasureHunt' do pod 'GVRKit' + pod 'GVRAudioSDK' end diff --git a/Samples/TreasureHunt/noise_sample.wav b/Samples/TreasureHunt/noise_sample.wav deleted file mode 100644 index ac7b323..0000000 Binary files a/Samples/TreasureHunt/noise_sample.wav and /dev/null differ diff --git a/Samples/TreasureHuntNDK/Podfile b/Samples/TreasureHuntNDK/Podfile index 23d08b6..771b9a4 100644 --- a/Samples/TreasureHuntNDK/Podfile +++ b/Samples/TreasureHuntNDK/Podfile @@ -1,3 +1,4 @@ target 'TreasureHuntNDK' do pod 'GVRSDK' + pod 'GVRAudioSDK' end diff --git a/Samples/TreasureHuntNDK/noise_sample.wav b/Samples/TreasureHuntNDK/noise_sample.wav deleted file mode 100644 index ac7b323..0000000 Binary files a/Samples/TreasureHuntNDK/noise_sample.wav and /dev/null differ