#version 330 core

/*
 * === UCSF ChimeraX Copyright ===
# Copyright 2022 Regents of the University of California. All rights reserved.
# The ChimeraX application is provided pursuant to the ChimeraX license
# agreement, which covers academic and commercial uses. For more details, see
# <http://www.rbvi.ucsf.edu/chimerax/docs/licensing.html>
#
# This particular file is part of the ChimeraX library. You can also
# redistribute and/or modify it under the terms of the GNU Lesser General
# Public License version 2.1 as published by the Free Software Foundation.
# For more details, see
# <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>
#
# THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ADDITIONAL LIABILITY
# LIMITATIONS ARE DESCRIBED IN THE GNU LESSER GENERAL PUBLIC LICENSE
# VERSION 2.1
#
# This notice must be embedded in or attached to all copies, including partial
# copies, of the software or any revisions or derivations thereof.
 * === UCSF ChimeraX Copyright ===
 */

#if defined(USE_TEXTURE_OUTLINE) || defined(USE_DEPTH_OUTLINE) || defined(USE_BLEND_TEXTURE_2D) || defined(USE_BLEND_TEXTURE_3D)

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 tex_coord;
out vec2 tex_coord_2d;
void main(void)
{
  tex_coord_2d = tex_coord;
  gl_Position = vec4(position,1);
}

#else

#if defined(USE_CLIP_PLANES) || defined(USE_STEREO_360)
uniform mat4 model_matrix;	// Map model coordinates to scene coordinates
#endif

#if defined(USE_STEREO_360)
uniform mat4 view_matrix;	// Map scene coordinates to camera coordinates
#endif

uniform mat4 model_view_matrix;	// Map model coordinates to camera coordinates
uniform mat4 projection_matrix;

layout(location = 0) in vec3 position;

#if defined(USE_LIGHTING) || defined(USE_DEPTH_CUE)
out vec3 v;
#endif

#ifdef USE_LIGHTING

#ifdef USE_LIGHTING_NORMALS
layout(location = 2) in vec3 normal;
out vec3 N;
#endif

#ifdef USE_SHADOW
uniform mat4 shadow_transform;
out vec3 shadow_tex_coord;
#endif

#ifdef USE_MULTISHADOW
//out vec3 vscene;
//out vec3 nscene;
#endif

#ifdef USE_TEXTURE_3D_AMBIENT
uniform mat4 ambient_tex3d_transform;
out vec3 ambient_tex_coord;
#endif

#endif	// end USE_LIGHTING

#ifdef USE_VERTEX_COLORS
layout(location = 3) in vec4 vcolor;
out vec4 color;
#endif

#ifdef USE_TEXTURE_2D
layout(location = 1) in vec2 tex_coord;
out vec2 tex_coord_2d;
#endif

#ifdef USE_TEXTURE_3D
layout(location = 1) in vec3 tex_coord;
out vec3 tex_coord_3d;
#endif

#ifdef USE_TEXTURE_CUBEMAP
layout(location = 1) in vec3 tex_coord;
out vec3 tex_coord_cubemap;
#endif

#ifdef USE_SHIFT_AND_SCALE
layout(location = 4) in vec4 instance_shift_and_scale;
#endif

#ifdef USE_INSTANCING
layout(location = 5) in mat4 instance_placement;
#endif

#ifdef USE_FRAME_NUMBER
uniform float frame_number;
#endif

#ifdef USE_STEREO_360
#ifdef USE_LIGHTING
out vec3 vshadow;
#endif
uniform vec4 camera_origin_and_shift;
uniform vec4 camera_vertical;
#endif

#ifdef USE_CLIP_PLANES
uniform int num_clip_planes;
uniform vec4 clip_planes[8];	// Normal in scene coordinates and offset
out float gl_ClipDistance[8];
#endif

void main(void)
{
#ifdef USE_SHIFT_AND_SCALE
  vec4 vi = vec4(instance_shift_and_scale.w * position + instance_shift_and_scale.xyz, 1);
#else
  #ifdef USE_INSTANCING
    vec4 vi = instance_placement * vec4(position, 1);
  #else
    vec4 vi = vec4(position,1);
  #endif
#endif

#ifdef USE_CLIP_PLANES
  vec4 vscene_c = model_matrix * vi;
  for (int i = 0 ; i < num_clip_planes ; ++i)
    gl_ClipDistance[i] = dot(vscene_c, clip_planes[i]);
#endif

#ifdef USE_STEREO_360
  vec4 vscene_s = model_matrix * vi;
  vec3 eye_axis = normalize(cross((vscene_s.xyz - camera_origin_and_shift.xyz),
                                  camera_vertical.xyz));
  vec4 vsoffset = vec4(vscene_s.xyz - camera_origin_and_shift.w * eye_axis, 1);
  vec4 veye = view_matrix * vsoffset;
#ifdef USE_LIGHTING
  vshadow = (model_view_matrix * vi).xyz;
  // vshadow = (model_matrix * vi).xyz;
#endif
#else
  vec4 veye = model_view_matrix * vi;
#endif

#if defined(USE_LIGHTING) || defined(USE_DEPTH_CUE)
   v = veye.xyz;
#endif

#ifdef USE_LIGHTING
  #ifdef USE_LIGHTING_NORMALS
    #ifdef USE_INSTANCING
      vec3 ni = vec3(instance_placement * vec4(normal,0));
    #else
      vec3 ni = normal;
    #endif
    N = normalize((model_view_matrix * vec4(ni,0)).xyz);
  #endif
  #ifdef USE_SHADOW
    #ifdef USE_STEREO_360
      shadow_tex_coord = (shadow_transform * (view_matrix * vec4(vshadow,1))).stp;
    #else
      shadow_tex_coord = (shadow_transform * veye).stp;
    #endif
  #endif
  #ifdef USE_MULTISHADOW
//    vscene = (model_matrix * vi).xyz;
//    nscene = (model_matrix * vec4(ni,0)).xyz;
  #endif
  #ifdef USE_TEXTURE_3D_AMBIENT
  // TODO: This should use vertex scene coords, not vertex model coordinates
    ambient_tex_coord = (ambient_tex3d_transform * vi).xyz;
  #endif
#endif	// end USE_LIGHTING

#ifdef USE_VERTEX_COLORS
  color = vcolor;
#endif

#ifdef USE_TEXTURE_2D
  tex_coord_2d = tex_coord;
#endif

#ifdef USE_TEXTURE_3D
  tex_coord_3d = tex_coord;
#endif

#ifdef USE_TEXTURE_CUBEMAP
  tex_coord_cubemap = tex_coord;
#endif

  gl_Position = projection_matrix * veye;
}

#endif
