Fixup of previous commit (4ae7a7c): actually add the files into the repository

This commit is contained in:
Lukas Matena 2024-07-08 16:06:13 +02:00
parent 8fff3fd8a1
commit f7d8e20beb
52 changed files with 15659 additions and 0 deletions

View File

@ -0,0 +1,80 @@
cmake_minimum_required(VERSION 3.13)
project(libvgcode)
# glad library
if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
set(GLAD_SOURCES
glad/include/glad/gles2.h
glad/include/KHR/khrplatform.h
glad/src/gles2.c
)
else ()
set(GLAD_SOURCES
glad/include/glad/gl.h
glad/include/KHR/khrplatform.h
glad/src/gl.c
)
endif ()
set(LIBVGCODE_SOURCES
# API
include/ColorPrint.hpp
include/ColorRange.hpp
include/GCodeInputData.hpp
include/PathVertex.hpp
include/Types.hpp
include/Viewer.hpp
# source
src/Bitset.hpp
src/Bitset.cpp
src/CogMarker.hpp
src/CogMarker.cpp
src/ColorPrint.cpp
src/ColorRange.cpp
src/ExtrusionRoles.hpp
src/ExtrusionRoles.cpp
src/GCodeInputData.cpp
src/Layers.hpp
src/Layers.cpp
src/OpenGLUtils.hpp
src/OpenGLUtils.cpp
src/OptionTemplate.hpp
src/OptionTemplate.cpp
src/PathVertex.cpp
src/Range.hpp
src/Range.cpp
src/SegmentTemplate.hpp
src/SegmentTemplate.cpp
src/Settings.hpp
src/Settings.cpp
src/Shaders.hpp
src/ShadersES.hpp
src/ToolMarker.hpp
src/ToolMarker.cpp
src/Types.cpp
src/Utils.hpp
src/Utils.cpp
src/Viewer.cpp
src/ViewerImpl.hpp
src/ViewerImpl.cpp
src/ViewRange.hpp
src/ViewRange.cpp
${GLAD_SOURCES}
)
add_library(libvgcode STATIC ${LIBVGCODE_SOURCES})
if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
add_compile_definitions(ENABLE_OPENGL_ES)
endif()
if (WIN32)
foreach(_source IN ITEMS ${LIBVGCODE_SOURCES})
get_filename_component(_source_path "${_source}" PATH)
string(REPLACE "/" "\\" _group_path "${_source_path}")
source_group("${_group_path}" FILES "${_source}")
endforeach()
endif ()
# glad includes
include_directories(glad/include)

View File

@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1786
src/libvgcode/glad/src/gl.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,877 @@
/**
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glad/gles2.h>
#ifndef GLAD_IMPL_UTIL_C_
#define GLAD_IMPL_UTIL_C_
#ifdef _MSC_VER
#define GLAD_IMPL_UTIL_SSCANF sscanf_s
#else
#define GLAD_IMPL_UTIL_SSCANF sscanf
#endif
#endif /* GLAD_IMPL_UTIL_C_ */
#ifdef __cplusplus
extern "C" {
#endif
int GLAD_GL_ES_VERSION_2_0 = 0;
int GLAD_GL_ES_VERSION_3_0 = 0;
PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
PFNGLCLEARPROC glad_glClear = NULL;
PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
PFNGLCOLORMASKPROC glad_glColorMask = NULL;
PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
PFNGLCULLFACEPROC glad_glCullFace = NULL;
PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL;
PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
PFNGLDISABLEPROC glad_glDisable = NULL;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
PFNGLENABLEPROC glad_glEnable = NULL;
PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
PFNGLENDQUERYPROC glad_glEndQuery = NULL;
PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
PFNGLFINISHPROC glad_glFinish = NULL;
PFNGLFLUSHPROC glad_glFlush = NULL;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
PFNGLGETERRORPROC glad_glGetError = NULL;
PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL;
PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
PFNGLGETSTRINGPROC glad_glGetString = NULL;
PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
PFNGLHINTPROC glad_glHint = NULL;
PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
PFNGLISQUERYPROC glad_glIsQuery = NULL;
PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
PFNGLISSHADERPROC glad_glIsShader = NULL;
PFNGLISSYNCPROC glad_glIsSync = NULL;
PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL;
PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL;
PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL;
PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL;
PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL;
PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
PFNGLSCISSORPROC glad_glScissor = NULL;
PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL;
PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL;
PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
PFNGLVIEWPORTPROC glad_glViewport = NULL;
PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
static void glad_gl_load_GL_ES_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ES_VERSION_2_0) return;
glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf");
glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef");
glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat");
glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler");
glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary");
glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
}
static void glad_gl_load_GL_ES_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ES_VERSION_3_0) return;
glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery");
glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback");
glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler");
glad_glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC) load(userptr, "glBindTransformFeedback");
glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi");
glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv");
glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv");
glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv");
glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync");
glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D");
glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D");
glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D");
glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries");
glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers");
glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync");
glad_glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC) load(userptr, "glDeleteTransformFeedbacks");
glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced");
glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers");
glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced");
glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements");
glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery");
glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback");
glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync");
glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries");
glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers");
glad_glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC) load(userptr, "glGenTransformFeedbacks");
glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v");
glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv");
glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation");
glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v");
glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v");
glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) load(userptr, "glGetInternalformativ");
glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) load(userptr, "glGetProgramBinary");
glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv");
glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv");
glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv");
glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv");
glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi");
glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv");
glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying");
glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv");
glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv");
glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv");
glad_glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC) load(userptr, "glInvalidateFramebuffer");
glad_glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC) load(userptr, "glInvalidateSubFramebuffer");
glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery");
glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler");
glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync");
glad_glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC) load(userptr, "glIsTransformFeedback");
glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
glad_glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC) load(userptr, "glPauseTransformFeedback");
glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC) load(userptr, "glProgramBinary");
glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) load(userptr, "glProgramParameteri");
glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer");
glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
glad_glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC) load(userptr, "glResumeTransformFeedback");
glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf");
glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv");
glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri");
glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv");
glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D");
glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) load(userptr, "glTexStorage2D");
glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) load(userptr, "glTexStorage3D");
glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D");
glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings");
glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui");
glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv");
glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui");
glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv");
glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui");
glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv");
glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui");
glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv");
glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv");
glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv");
glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv");
glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv");
glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv");
glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv");
glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer");
glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor");
glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i");
glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv");
glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui");
glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv");
glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer");
glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync");
}
static void glad_gl_free_extensions(char **exts_i) {
if (exts_i != NULL) {
unsigned int index;
for(index = 0; exts_i[index]; index++) {
free((void *) (exts_i[index]));
}
free((void *)exts_i);
exts_i = NULL;
}
}
static int glad_gl_get_extensions( const char **out_exts, char ***out_exts_i) {
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
if (glad_glGetStringi != NULL && glad_glGetIntegerv != NULL) {
unsigned int index = 0;
unsigned int num_exts_i = 0;
char **exts_i = NULL;
glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
exts_i = (char **) malloc((num_exts_i + 1) * (sizeof *exts_i));
if (exts_i == NULL) {
return 0;
}
for(index = 0; index < num_exts_i; index++) {
const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
size_t len = strlen(gl_str_tmp) + 1;
char *local_str = (char*) malloc(len * sizeof(char));
if(local_str == NULL) {
exts_i[index] = NULL;
glad_gl_free_extensions(exts_i);
return 0;
}
memcpy(local_str, gl_str_tmp, len * sizeof(char));
exts_i[index] = local_str;
}
exts_i[index] = NULL;
*out_exts_i = exts_i;
return 1;
}
#else
GLAD_UNUSED(out_exts_i);
#endif
if (glad_glGetString == NULL) {
return 0;
}
*out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
return 1;
}
static int glad_gl_has_extension(const char *exts, char **exts_i, const char *ext) {
if(exts_i) {
unsigned int index;
for(index = 0; exts_i[index]; index++) {
const char *e = exts_i[index];
if(strcmp(e, ext) == 0) {
return 1;
}
}
} else {
const char *extensions;
const char *loc;
const char *terminator;
extensions = exts;
if(extensions == NULL || ext == NULL) {
return 0;
}
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL) {
return 0;
}
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\0')) {
return 1;
}
extensions = terminator;
}
}
return 0;
}
static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
}
static int glad_gl_find_extensions_gles2(void) {
const char *exts = NULL;
char **exts_i = NULL;
if (!glad_gl_get_extensions(&exts, &exts_i)) return 0;
GLAD_UNUSED(glad_gl_has_extension);
glad_gl_free_extensions(exts_i);
return 1;
}
static int glad_gl_find_core_gles2(void) {
int i;
const char* version;
const char* prefixes[] = {
"OpenGL ES-CM ",
"OpenGL ES-CL ",
"OpenGL ES ",
"OpenGL SC ",
NULL
};
int major = 0;
int minor = 0;
version = (const char*) glad_glGetString(GL_VERSION);
if (!version) return 0;
for (i = 0; prefixes[i]; i++) {
const size_t length = strlen(prefixes[i]);
if (strncmp(version, prefixes[i], length) == 0) {
version += length;
break;
}
}
GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
GLAD_GL_ES_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
return GLAD_MAKE_VERSION(major, minor);
}
int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) {
int version;
glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
if(glad_glGetString == NULL) return 0;
version = glad_gl_find_core_gles2();
glad_gl_load_GL_ES_VERSION_2_0(load, userptr);
glad_gl_load_GL_ES_VERSION_3_0(load, userptr);
if (!glad_gl_find_extensions_gles2()) return 0;
return version;
}
int gladLoadGLES2( GLADloadfunc load) {
return gladLoadGLES2UserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
}
#ifdef GLAD_GLES2
#ifndef GLAD_LOADER_LIBRARY_C_
#define GLAD_LOADER_LIBRARY_C_
#include <stddef.h>
#include <stdlib.h>
#if GLAD_PLATFORM_WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
void *handle = NULL;
int i;
for (i = 0; i < length; ++i) {
#if GLAD_PLATFORM_WIN32
#if GLAD_PLATFORM_UWP
size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
LPWSTR buffer = (LPWSTR) malloc(buffer_size);
if (buffer != NULL) {
int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
if (ret != 0) {
handle = (void*) LoadPackagedLibrary(buffer, 0);
}
free((void*) buffer);
}
#else
handle = (void*) LoadLibraryA(lib_names[i]);
#endif
#else
handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
#endif
if (handle != NULL) {
return handle;
}
}
return NULL;
}
static void glad_close_dlopen_handle(void* handle) {
if (handle != NULL) {
#if GLAD_PLATFORM_WIN32
FreeLibrary((HMODULE) handle);
#else
dlclose(handle);
#endif
}
}
static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
if (handle == NULL) {
return NULL;
}
#if GLAD_PLATFORM_WIN32
return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
#else
return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
#endif
}
#endif /* GLAD_LOADER_LIBRARY_C_ */
#if GLAD_PLATFORM_EMSCRIPTEN
#ifndef GLAD_EGL_H_
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char *name);
#endif
extern __eglMustCastToProperFunctionPointerType emscripten_GetProcAddress(const char *name);
#elif GLAD_GLES2_USE_SYSTEM_EGL
#include <EGL/egl.h>
typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char *name);
#else
#include <glad/egl.h>
#endif
struct _glad_gles2_userptr {
void *handle;
PFNEGLGETPROCADDRESSPROC get_proc_address_ptr;
};
static GLADapiproc glad_gles2_get_proc(void *vuserptr, const char* name) {
struct _glad_gles2_userptr userptr = *(struct _glad_gles2_userptr*) vuserptr;
GLADapiproc result = NULL;
#if GLAD_PLATFORM_EMSCRIPTEN
GLAD_UNUSED(glad_dlsym_handle);
#else
result = glad_dlsym_handle(userptr.handle, name);
#endif
if (result == NULL) {
result = userptr.get_proc_address_ptr(name);
}
return result;
}
static void* _glad_GLES2_loader_handle = NULL;
static void* glad_gles2_dlopen_handle(void) {
#if GLAD_PLATFORM_EMSCRIPTEN
#elif GLAD_PLATFORM_APPLE
static const char *NAMES[] = {"libGLESv2.dylib"};
#elif GLAD_PLATFORM_WIN32
static const char *NAMES[] = {"GLESv2.dll", "libGLESv2.dll"};
#else
static const char *NAMES[] = {"libGLESv2.so.2", "libGLESv2.so"};
#endif
#if GLAD_PLATFORM_EMSCRIPTEN
GLAD_UNUSED(glad_get_dlopen_handle);
return NULL;
#else
if (_glad_GLES2_loader_handle == NULL) {
_glad_GLES2_loader_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
}
return _glad_GLES2_loader_handle;
#endif
}
static struct _glad_gles2_userptr glad_gles2_build_userptr(void *handle) {
struct _glad_gles2_userptr userptr;
#if GLAD_PLATFORM_EMSCRIPTEN
GLAD_UNUSED(handle);
userptr.get_proc_address_ptr = emscripten_GetProcAddress;
#else
userptr.handle = handle;
userptr.get_proc_address_ptr = eglGetProcAddress;
#endif
return userptr;
}
int gladLoaderLoadGLES2(void) {
int version = 0;
void *handle = NULL;
int did_load = 0;
struct _glad_gles2_userptr userptr;
#if GLAD_PLATFORM_EMSCRIPTEN
GLAD_UNUSED(handle);
GLAD_UNUSED(did_load);
GLAD_UNUSED(glad_gles2_dlopen_handle);
GLAD_UNUSED(glad_gles2_build_userptr);
userptr.get_proc_address_ptr = emscripten_GetProcAddress;
version = gladLoadGLES2UserPtr(glad_gles2_get_proc, &userptr);
#else
if (eglGetProcAddress == NULL) {
return 0;
}
did_load = _glad_GLES2_loader_handle == NULL;
handle = glad_gles2_dlopen_handle();
if (handle != NULL) {
userptr = glad_gles2_build_userptr(handle);
version = gladLoadGLES2UserPtr(glad_gles2_get_proc, &userptr);
if (!version && did_load) {
gladLoaderUnloadGLES2();
}
}
#endif
return version;
}
void gladLoaderUnloadGLES2(void) {
if (_glad_GLES2_loader_handle != NULL) {
glad_close_dlopen_handle(_glad_GLES2_loader_handle);
_glad_GLES2_loader_handle = NULL;
}
}
#endif /* GLAD_GLES2 */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,22 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_COLORPRINT_HPP
#define VGCODE_COLORPRINT_HPP
#include "../include/Types.hpp"
namespace libvgcode {
struct ColorPrint
{
uint8_t extruder_id{ 0 };
uint8_t color_id{ 0 };
uint32_t layer_id{ 0 };
std::array<float, TIME_MODES_COUNT> times{ 0.0f, 0.0f };
};
} // namespace libvgcode
#endif // VGCODE_COLORPRINT_HPP

View File

@ -0,0 +1,107 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_COLORRANGE_HPP
#define VGCODE_COLORRANGE_HPP
#include "../include/Types.hpp"
#include <cfloat>
namespace libvgcode {
static const Palette DEFAULT_RANGES_COLORS{ {
{ 11, 44, 122 }, // bluish
{ 19, 89, 133 },
{ 28, 136, 145 },
{ 4, 214, 15 },
{ 170, 242, 0 },
{ 252, 249, 3 },
{ 245, 206, 10 },
{ 227, 136, 32 },
{ 209, 104, 48 },
{ 194, 82, 60 },
{ 148, 38, 22 } // reddish
} };
class ColorRange
{
public:
//
// Constructor
//
explicit ColorRange(EColorRangeType type = EColorRangeType::Linear);
//
// Return the type of this ColorRange.
//
EColorRangeType get_type() const;
//
// Return the palette used by this ColorRange.
// Default is DEFAULT_RANGES_COLORS
//
const Palette& get_palette() const;
//
// Set the palette to be used by this ColorRange.
// The given palette must contain at least two colors.
//
void set_palette(const Palette& palette);
//
// Return the interpolated color at the given value.
// Value is clamped to [get_range()[0]..get_range()[1]].
//
Color get_color_at(float value) const;
//
// Return the range of this ColorRange.
// The range is detected during the call to Viewer::load().
// [0] -> min
// [1] -> max
//
const std::array<float, 2>& get_range() const;
//
// Return the values corresponding to the detected color bins of this ColorRange.
// The size of the returned vector can be:
// 1 - If only one value was detected while setting up this ColorRange.
// 2 - If only two values were detected while setting up this ColorRange.
// get_palette().size() - If more than two distinct values were detected while setting up this ColorRange.
//
std::vector<float> get_values() const;
//
// Return the size of the palette, in bytes
//
std::size_t size_in_bytes_cpu() const;
static const ColorRange DUMMY_COLOR_RANGE;
private:
EColorRangeType m_type{ EColorRangeType::Linear };
//
// The palette used by this ColorRange
//
Palette m_palette;
//
// [0] = min
// [1] = max
//
std::array<float, 2> m_range{ FLT_MAX, -FLT_MAX };
//
// Count of different values passed to update()
//
std::size_t m_count{ 0 };
//
// Use the passed value to update the range.
//
void update(float value);
//
// Reset the range
// Call this method before reuse an instance of ColorRange.
//
void reset();
friend class ViewerImpl;
};
} // namespace libvgcode
#endif // VGCODE_COLORRANGE_HPP

View File

@ -0,0 +1,36 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_GCODEINPUTDATA_HPP
#define VGCODE_GCODEINPUTDATA_HPP
#include "PathVertex.hpp"
namespace libvgcode {
struct GCodeInputData
{
//
// Whether or not the gcode was generated with spiral vase mode enabled.
// Required to properly detect fictitious layer changes when spiral vase mode is enabled.
//
bool spiral_vase_mode{ false };
//
// List of path vertices (gcode moves)
// See: PathVertex
//
std::vector<PathVertex> vertices;
//
// Palette for extruders colors
//
Palette tools_colors;
//
// Palette for color print colors
//
Palette color_print_colors;
};
} // namespace libvgcode
#endif // VGCODE_BITSET_HPP

View File

@ -0,0 +1,121 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_PATHVERTEX_HPP
#define VGCODE_PATHVERTEX_HPP
#include "Types.hpp"
#include <cfloat>
namespace libvgcode {
//
// Struct representating a gcode move (toolpath segment)
//
struct PathVertex
{
//
// Segment end position
//
Vec3 position{ FLT_MAX, FLT_MAX, FLT_MAX };
//
// Segment height
//
float height{ 0.0f };
//
// Segment width
//
float width{ 0.0f };
//
// Segment speed
//
float feedrate{ 0.0f };
//
// Segment actual speed
//
float actual_feedrate{ 0.0f };
//
// Segment mm3_per_mm
//
float mm3_per_mm{ 0.0f };
//
// Segment fan speed
//
float fan_speed{ 0.0f };
//
// Segment temperature
//
float temperature{ 0.0f };
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Segment weight
//
float weight{ 0.0f };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Segment extrusion role
//
EGCodeExtrusionRole role{ EGCodeExtrusionRole::None };
//
// Segment move type
//
EMoveType type{ EMoveType::Noop };
//
// Segment gcode line id
//
uint32_t gcode_id{ 0 };
//
// Segment layer id
//
uint32_t layer_id{ 0 };
//
// Segment extruder id
//
uint8_t extruder_id{ 0 };
//
// Segment color id
//
uint8_t color_id{ 0 };
//
// Segment estimated times
//
std::array<float, TIME_MODES_COUNT> times{ 0.0f, 0.0f };
//
// Return true if the segment is an extrusion move
//
bool is_extrusion() const;
//
// Return true if the segment is an travel move
//
bool is_travel() const;
//
// Return true if the segment is an option
// See: EOptionType
//
bool is_option() const;
//
// Return true if the segment is a wipe move
//
bool is_wipe() const;
//
// Return true if the segment was generated by custom gcode
//
bool is_custom_gcode() const;
//
// Return the volumetric flow rate of the segment
//
float volumetric_rate() const { return feedrate * mm3_per_mm; }
//
// Return the acutal volumetric flow rate of the segment
//
float actual_volumetric_rate() const { return actual_feedrate * mm3_per_mm; }
static const PathVertex DUMMY_PATH_VERTEX;
};
} // namespace libvgcode
#endif // VGCODE_PATHVERTEX_HPP

View File

@ -0,0 +1,218 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_TYPES_HPP
#define VGCODE_TYPES_HPP
#define VGCODE_ENABLE_COG_AND_TOOL_MARKERS 0
#include <array>
#include <vector>
#include <cstdint>
namespace libvgcode {
static constexpr float PI = 3.141592f;
//
// Predefined values for the radius, in mm, of the cylinders used to render the travel moves.
//
static constexpr float DEFAULT_TRAVELS_RADIUS_MM = 0.1f;
static constexpr float MIN_TRAVELS_RADIUS_MM = 0.05f;
static constexpr float MAX_TRAVELS_RADIUS_MM = 1.0f;
//
// Predefined values for the radius, in mm, of the cylinders used to render the wipe moves.
//
static constexpr float DEFAULT_WIPES_RADIUS_MM = 0.1f;
static constexpr float MIN_WIPES_RADIUS_MM = 0.05f;
static constexpr float MAX_WIPES_RADIUS_MM = 1.0f;
//
// Vector in 3 dimensions
// [0] -> x
// [1] -> y
// [2] -> z
// Used for positions, displacements and so on.
//
using Vec3 = std::array<float, 3>;
//
// 4x4 square matrix with elements in column-major order:
// | a[0] a[4] a[8] a[12] |
// | a[1] a[5] a[9] a[13] |
// | a[2] a[6] a[10] a[14] |
// | a[3] a[7] a[11] a[15] |
//
using Mat4x4 = std::array<float, 16>;
//
// RGB color
// [0] -> red
// [1] -> green
// [2] -> blue
//
using Color = std::array<uint8_t, 3>;
//
// Color palette
//
using Palette = std::vector<Color>;
//
// Axis aligned box in 3 dimensions
// [0] -> { min_x, min_y, min_z }
// [1] -> { max_x, max_y, max_z }
//
using AABox = std::array<Vec3, 2>;
//
// One dimensional natural numbers interval
// [0] -> min
// [1] -> max
//
using Interval = std::array<std::size_t, 2>;
//
// View types
//
enum class EViewType : uint8_t
{
FeatureType,
Height,
Width,
Speed,
ActualSpeed,
FanSpeed,
Temperature,
VolumetricFlowRate,
ActualVolumetricFlowRate,
LayerTimeLinear,
LayerTimeLogarithmic,
Tool,
ColorPrint,
COUNT
};
static constexpr std::size_t VIEW_TYPES_COUNT = static_cast<std::size_t>(EViewType::COUNT);
//
// Move types
//
enum class EMoveType : uint8_t
{
Noop,
Retract,
Unretract,
Seam,
ToolChange,
ColorChange,
PausePrint,
CustomGCode,
Travel,
Wipe,
Extrude,
COUNT
};
static constexpr std::size_t MOVE_TYPES_COUNT = static_cast<std::size_t>(EMoveType::COUNT);
//
// Extrusion roles
//
enum class EGCodeExtrusionRole : uint8_t
{
// This enum is used as in index into extrusion_roles_visibility.
// Better only add things to the end.
None,
Perimeter,
ExternalPerimeter,
OverhangPerimeter,
InternalInfill,
SolidInfill,
TopSolidInfill,
Ironing,
BridgeInfill,
GapFill,
Skirt,
SupportMaterial,
SupportMaterialInterface,
WipeTower,
Custom,
COUNT
};
static constexpr std::size_t GCODE_EXTRUSION_ROLES_COUNT = static_cast<std::size_t>(EGCodeExtrusionRole::COUNT);
//
// Option types
//
enum class EOptionType : uint8_t
{
// This enum is used as in index into options_visibility.
// Better only add things to the end.
Travels,
Wipes,
Retractions,
Unretractions,
Seams,
ToolChanges,
ColorChanges,
PausePrints,
CustomGCodes,
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
CenterOfGravity,
ToolMarker,
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
COUNT
};
static constexpr std::size_t OPTION_TYPES_COUNT = static_cast<std::size_t>(EOptionType::COUNT);
//
// Time modes
//
enum class ETimeMode : uint8_t
{
Normal,
Stealth,
COUNT
};
static constexpr std::size_t TIME_MODES_COUNT = static_cast<std::size_t>(ETimeMode::COUNT);
//
// Color range types
//
enum class EColorRangeType : uint8_t
{
Linear,
Logarithmic,
COUNT
};
static constexpr std::size_t COLOR_RANGE_TYPES_COUNT = static_cast<std::size_t>(EColorRangeType::COUNT);
//
// Predefined colors
//
static const Color DUMMY_COLOR{ 64, 64, 64 };
//
// Mapping from EMoveType to EOptionType
// Returns EOptionType::COUNT if the given move type does not correspond
// to any option type.
//
extern EOptionType move_type_to_option(EMoveType type);
//
// Returns the linear interpolation between the two given colors
// at the given t.
// t is clamped in the range [0..1]
//
extern Color lerp(const Color& c1, const Color& c2, float t);
} // namespace libvgcode
#endif // VGCODE_TYPES_HPP

View File

@ -0,0 +1,419 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_VIEWER_HPP
#define VGCODE_VIEWER_HPP
#include "Types.hpp"
#include <string>
namespace libvgcode {
class ViewerImpl;
struct GCodeInputData;
struct PathVertex;
class ColorRange;
struct ColorPrint;
class Viewer
{
public:
Viewer();
~Viewer();
Viewer(const Viewer& other) = delete;
Viewer(Viewer&& other) = delete;
Viewer& operator = (const Viewer& other) = delete;
Viewer& operator = (Viewer&& other) = delete;
//
// Initialize the viewer.
// Param opengl_context_version must be the string returned by glGetString(GL_VERSION).
// This method must be called after a valid OpenGL context has been already created
// and before calling any other method of the viewer.
// Throws an std::runtime_error exception if:
// * the method is called before creating an OpenGL context
// * the created OpenGL context does not support OpenGL 3.2 or greater
// * when using OpenGL ES, the created OpenGL ES context does not support OpenGL ES 2.0 or greater
// * any of the shaders fails to compile
//
void init(const std::string& opengl_context_version);
//
// Release the resources used by the viewer.
// This method must be called before releasing the OpenGL context if the viewer
// goes out of scope after releasing it.
//
void shutdown();
//
// Reset the contents of the viewer.
// Automatically called by load() method.
//
void reset();
//
// Setup the viewer content from the given data.
// See: GCodeInputData
//
void load(GCodeInputData&& gcode_data);
//
// Render the toolpaths according to the current settings and
// using the given camera matrices.
//
void render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
//
// ************************************************************************
// Settings
// The following methods can be used to query/customize the parameters
// used to render the toolpaths.
// ************************************************************************
//
//
// View type
// See: EViewType
//
EViewType get_view_type() const;
void set_view_type(EViewType type);
//
// Time mode
// See: ETimeMode
//
ETimeMode get_time_mode() const;
void set_time_mode(ETimeMode mode);
//
// Top layer only
// Whether or not the visible range is limited to the current top layer only.
//
bool is_top_layer_only_view_range() const;
//
// Toggle the top layer only state.
//
void toggle_top_layer_only_view_range();
//
// Returns true if the given option is visible.
//
bool is_option_visible(EOptionType type) const;
//
// Toggle the visibility state of the given option.
//
void toggle_option_visibility(EOptionType type);
//
// Returns true if the given extrusion role is visible.
//
bool is_extrusion_role_visible(EGCodeExtrusionRole role) const;
//
// Toggle the visibility state of the given extrusion role.
//
void toggle_extrusion_role_visibility(EGCodeExtrusionRole role);
//
// Return the color used to render the given extrusion rols.
//
const Color& get_extrusion_role_color(EGCodeExtrusionRole role) const;
//
// Set the color used to render the given extrusion role.
//
void set_extrusion_role_color(EGCodeExtrusionRole role, const Color& color);
//
// Reset the colors used to render the extrusion roles to the default value.
//
void reset_default_extrusion_roles_colors();
//
// Return the color used to render the given option.
//
const Color& get_option_color(EOptionType type) const;
//
// Set the color used to render the given option.
//
void set_option_color(EOptionType type, const Color& color);
//
// Reset the colors used to render the options to the default value.
//
void reset_default_options_colors();
//
// Return the count of colors in the palette used to render
// the toolpaths when the view type is EViewType::Tool.
//
size_t get_tool_colors_count() const;
//
// Return the palette used to render the toolpaths when
// the view type is EViewType::Tool.
//
const Palette& get_tool_colors() const;
//
// Set the palette used to render the toolpaths when
// the view type is EViewType::Tool with the given one.
//
void set_tool_colors(const Palette& colors);
//
// Return the count of colors in the palette used to render
// the toolpaths when the view type is EViewType::ColorPrint.
//
size_t get_color_print_colors_count() const;
//
// Return the palette used to render the toolpaths when
// the view type is EViewType::ColorPrint.
//
const Palette& get_color_print_colors() const;
//
// Set the palette used to render the toolpaths when
// the view type is EViewType::ColorPrint with the given one.
//
void set_color_print_colors(const Palette& colors);
//
// Get the color range for the given view type.
// Valid view types are:
// EViewType::Height
// EViewType::Width
// EViewType::Speed
// EViewType::ActualSpeed
// EViewType::FanSpeed
// EViewType::Temperature
// EViewType::VolumetricFlowRate
// EViewType::ActualVolumetricFlowRate
// EViewType::LayerTimeLinear
// EViewType::LayerTimeLogarithmic
//
const ColorRange& get_color_range(EViewType type) const;
//
// Set the palette for the color range corresponding to the given view type
// with the given value.
// Valid view types are:
// EViewType::Height
// EViewType::Width
// EViewType::Speed
// EViewType::ActualSpeed
// EViewType::FanSpeed
// EViewType::Temperature
// EViewType::VolumetricFlowRate
// EViewType::ActualVolumetricFlowRate
// EViewType::LayerTimeLinear
// EViewType::LayerTimeLogarithmic
//
void set_color_range_palette(EViewType type, const Palette& palette);
//
// Get the radius, in mm, of the cylinders used to render the travel moves.
//
float get_travels_radius() const;
//
// Set the radius, in mm, of the cylinders used to render the travel moves.
// Radius is clamped to [MIN_TRAVELS_RADIUS_MM..MAX_TRAVELS_RADIUS_MM]
//
void set_travels_radius(float radius);
//
// Get the radius, in mm, of the cylinders used to render the wipe moves.
//
float get_wipes_radius() const;
//
// Set the radius, in mm, of the cylinders used to render the wipe moves.
// Radius is clamped to [MIN_WIPES_RADIUS_MM..MAX_WIPES_RADIUS_MM]
//
void set_wipes_radius(float radius);
//
// Return the count of detected layers.
//
size_t get_layers_count() const;
//
// Return the current visible layers range.
//
const Interval& get_layers_view_range() const;
//
// Set the current visible layers range with the given interval.
// Values are clamped to [0..get_layers_count() - 1].
//
void set_layers_view_range(const Interval& range);
//
// Set the current visible layers range with the given min and max values.
// Values are clamped to [0..get_layers_count() - 1].
//
void set_layers_view_range(Interval::value_type min, Interval::value_type max);
//
// Return the current visible range.
// Three ranges are defined: full, enabled and visible.
// For all of them the range endpoints represent:
// [0] -> min vertex id
// [1] -> max vertex id
// Full is the range of vertices that could potentially be visualized accordingly to the current settings.
// Enabled is the part of the full range that is selected for visualization accordingly to the current settings.
// Visible is the part of the enabled range that is actually visualized accordingly to the current settings.
//
const Interval& get_view_visible_range() const;
//
// Set the current visible range.
// Values are clamped to the current view enabled range;
//
void set_view_visible_range(Interval::value_type min, Interval::value_type max);
//
// Return the current full range.
//
const Interval& get_view_full_range() const;
//
// Return the current enabled range.
//
const Interval& get_view_enabled_range() const;
//
// ************************************************************************
// Property getters
// The following methods can be used to query detected properties.
// ************************************************************************
//
//
// Spiral vase mode
// Whether or not the gcode was generated with spiral vase mode enabled.
// See: GCodeInputData
//
bool is_spiral_vase_mode() const;
//
// Return the z of the layer with the given id
// or 0.0f if the id does not belong to [0..get_layers_count() - 1].
//
float get_layer_z(size_t layer_id) const;
//
// Return the list of zs of the detected layers.
//
std::vector<float> get_layers_zs() const;
//
// Return the id of the layer closest to the given z.
//
size_t get_layer_id_at(float z) const;
//
// Return the count of detected used extruders.
//
size_t get_used_extruders_count() const;
//
// Return the list of ids of the detected used extruders.
//
std::vector<uint8_t> get_used_extruders_ids() const;
//
// Return the list of detected time modes.
//
std::vector<ETimeMode> get_time_modes() const;
//
// Return the count of vertices used to render the toolpaths
//
size_t get_vertices_count() const;
//
// Return the vertex pointed by the max value of the view visible range
//
const PathVertex& get_current_vertex() const;
//
// Return the index of vertex pointed by the max value of the view visible range
//
size_t get_current_vertex_id() const;
//
// Return the vertex at the given index
//
const PathVertex& get_vertex_at(size_t id) const;
//
// Return the total estimated time, in seconds, using the current time mode.
//
float get_estimated_time() const;
//
// Return the estimated time, in seconds, at the vertex with the given index
// using the current time mode.
//
float get_estimated_time_at(size_t id) const;
//
// Return the color used to render the given vertex with the current settings.
//
Color get_vertex_color(const PathVertex& vertex) const;
//
// Return the count of detected extrusion roles
//
size_t get_extrusion_roles_count() const;
//
// Return the list of detected extrusion roles
//
std::vector<EGCodeExtrusionRole> get_extrusion_roles() const;
//
// Return the count of detected options.
//
size_t get_options_count() const;
//
// Return the list of detected options.
//
const std::vector<EOptionType>& get_options() const;
//
// Return the count of detected color prints.
//
size_t get_color_prints_count(uint8_t extruder_id) const;
//
// Return the list of detected color prints.
//
std::vector<ColorPrint> get_color_prints(uint8_t extruder_id) const;
//
// Return the estimated time for the given role and the current time mode.
//
float get_extrusion_role_estimated_time(EGCodeExtrusionRole role) const;
//
// Return the estimated time for the travel moves and the current time mode.
//
float get_travels_estimated_time() const;
//
// Return the list of layers time for the current time mode.
//
std::vector<float> get_layers_estimated_times() const;
//
// Return the axes aligned bounding box containing all the given types.
//
AABox get_bounding_box(const std::vector<EMoveType>& types = {
EMoveType::Retract, EMoveType::Unretract, EMoveType::Seam, EMoveType::ToolChange,
EMoveType::ColorChange, EMoveType::PausePrint, EMoveType::CustomGCode, EMoveType::Travel,
EMoveType::Wipe, EMoveType::Extrude }) const;
//
// Return the axes aligned bounding box containing all the extrusions with the given roles.
//
AABox get_extrusion_bounding_box(const std::vector<EGCodeExtrusionRole>& roles = {
EGCodeExtrusionRole::Perimeter, EGCodeExtrusionRole::ExternalPerimeter, EGCodeExtrusionRole::OverhangPerimeter,
EGCodeExtrusionRole::InternalInfill, EGCodeExtrusionRole::SolidInfill, EGCodeExtrusionRole::TopSolidInfill,
EGCodeExtrusionRole::Ironing, EGCodeExtrusionRole::BridgeInfill, EGCodeExtrusionRole::GapFill,
EGCodeExtrusionRole::Skirt, EGCodeExtrusionRole::SupportMaterial, EGCodeExtrusionRole::SupportMaterialInterface,
EGCodeExtrusionRole::WipeTower, EGCodeExtrusionRole::Custom }) const;
//
// Return the size of the used cpu memory, in bytes
//
size_t get_used_cpu_memory() const;
//
// Return the size of the used gpu memory, in bytes
//
size_t get_used_gpu_memory() const;
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Returns the position of the center of gravity of the toolpaths.
// It does not take in account extrusions of type:
// Skirt
// Support Material
// Support Material Interface
// WipeTower
// Custom
//
Vec3 get_cog_position() const;
float get_cog_marker_scale_factor() const;
void set_cog_marker_scale_factor(float factor);
const Vec3& get_tool_marker_position() const;
float get_tool_marker_offset_z() const;
void set_tool_marker_offset_z(float offset_z);
float get_tool_marker_scale_factor() const;
void set_tool_marker_scale_factor(float factor);
const Color& get_tool_marker_color() const;
void set_tool_marker_color(const Color& color);
float get_tool_marker_alpha() const;
void set_tool_marker_alpha(float alpha);
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
private:
ViewerImpl* m_impl{ nullptr };
};
} // namespace libvgcode
#endif // VGCODE_VIEWER_HPP

View File

@ -0,0 +1,22 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_COLORPRINT_HPP
#define VGCODE_COLORPRINT_HPP
#include "Types.hpp"
namespace libvgcode {
struct ColorPrint
{
uint8_t extruder_id{ 0 };
uint8_t color_id{ 0 };
uint32_t layer_id{ 0 };
std::array<float, TIME_MODES_COUNT> times{ 0.0f, 0.0f };
};
} // namespace libvgcode
#endif // VGCODE_COLORPRINT_HPP

View File

@ -0,0 +1,107 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_COLORRANGE_HPP
#define VGCODE_COLORRANGE_HPP
#include "Types.hpp"
#include <cfloat>
namespace libvgcode {
static const Palette DEFAULT_RANGES_COLORS{ {
{ 11, 44, 122 }, // bluish
{ 19, 89, 133 },
{ 28, 136, 145 },
{ 4, 214, 15 },
{ 170, 242, 0 },
{ 252, 249, 3 },
{ 245, 206, 10 },
{ 227, 136, 32 },
{ 209, 104, 48 },
{ 194, 82, 60 },
{ 148, 38, 22 } // reddish
} };
class ColorRange
{
public:
//
// Constructor
//
explicit ColorRange(EColorRangeType type = EColorRangeType::Linear);
//
// Return the type of this ColorRange.
//
EColorRangeType get_type() const;
//
// Return the palette used by this ColorRange.
// Default is DEFAULT_RANGES_COLORS
//
const Palette& get_palette() const;
//
// Set the palette to be used by this ColorRange.
// The given palette must contain at least two colors.
//
void set_palette(const Palette& palette);
//
// Return the interpolated color at the given value.
// Value is clamped to [get_range()[0]..get_range()[1]].
//
Color get_color_at(float value) const;
//
// Return the range of this ColorRange.
// The range is detected during the call to Viewer::load().
// [0] -> min
// [1] -> max
//
const std::array<float, 2>& get_range() const;
//
// Return the values corresponding to the detected color bins of this ColorRange.
// The size of the returned vector can be:
// 1 - If only one value was detected while setting up this ColorRange.
// 2 - If only two values were detected while setting up this ColorRange.
// get_palette().size() - If more than two distinct values were detected while setting up this ColorRange.
//
std::vector<float> get_values() const;
//
// Return the size of the palette, in bytes
//
std::size_t size_in_bytes_cpu() const;
static const ColorRange DUMMY_COLOR_RANGE;
private:
EColorRangeType m_type{ EColorRangeType::Linear };
//
// The palette used by this ColorRange
//
Palette m_palette;
//
// [0] = min
// [1] = max
//
std::array<float, 2> m_range{ FLT_MAX, -FLT_MAX };
//
// Count of different values passed to update()
//
std::size_t m_count{ 0 };
//
// Use the passed value to update the range.
//
void update(float value);
//
// Reset the range
// Call this method before reuse an instance of ColorRange.
//
void reset();
friend class ViewerImpl;
};
} // namespace libvgcode
#endif // VGCODE_COLORRANGE_HPP

View File

@ -0,0 +1,36 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_GCODEINPUTDATA_HPP
#define VGCODE_GCODEINPUTDATA_HPP
#include "PathVertex.hpp"
namespace libvgcode {
struct GCodeInputData
{
//
// Whether or not the gcode was generated with spiral vase mode enabled.
// Required to properly detect fictitious layer changes when spiral vase mode is enabled.
//
bool spiral_vase_mode{ false };
//
// List of path vertices (gcode moves)
// See: PathVertex
//
std::vector<PathVertex> vertices;
//
// Palette for extruders colors
//
Palette tools_colors;
//
// Palette for color print colors
//
Palette color_print_colors;
};
} // namespace libvgcode
#endif // VGCODE_BITSET_HPP

View File

@ -0,0 +1,121 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_PATHVERTEX_HPP
#define VGCODE_PATHVERTEX_HPP
#include "Types.hpp"
#include <cfloat>
namespace libvgcode {
//
// Struct representating a gcode move (toolpath segment)
//
struct PathVertex
{
//
// Segment end position
//
Vec3 position{ FLT_MAX, FLT_MAX, FLT_MAX };
//
// Segment height
//
float height{ 0.0f };
//
// Segment width
//
float width{ 0.0f };
//
// Segment speed
//
float feedrate{ 0.0f };
//
// Segment actual speed
//
float actual_feedrate{ 0.0f };
//
// Segment mm3_per_mm
//
float mm3_per_mm{ 0.0f };
//
// Segment fan speed
//
float fan_speed{ 0.0f };
//
// Segment temperature
//
float temperature{ 0.0f };
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Segment weight
//
float weight{ 0.0f };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Segment extrusion role
//
EGCodeExtrusionRole role{ EGCodeExtrusionRole::None };
//
// Segment move type
//
EMoveType type{ EMoveType::Noop };
//
// Segment gcode line id
//
uint32_t gcode_id{ 0 };
//
// Segment layer id
//
uint32_t layer_id{ 0 };
//
// Segment extruder id
//
uint8_t extruder_id{ 0 };
//
// Segment color id
//
uint8_t color_id{ 0 };
//
// Segment estimated times
//
std::array<float, TIME_MODES_COUNT> times{ 0.0f, 0.0f };
//
// Return true if the segment is an extrusion move
//
bool is_extrusion() const;
//
// Return true if the segment is an travel move
//
bool is_travel() const;
//
// Return true if the segment is an option
// See: EOptionType
//
bool is_option() const;
//
// Return true if the segment is a wipe move
//
bool is_wipe() const;
//
// Return true if the segment was generated by custom gcode
//
bool is_custom_gcode() const;
//
// Return the volumetric flow rate of the segment
//
float volumetric_rate() const { return feedrate * mm3_per_mm; }
//
// Return the acutal volumetric flow rate of the segment
//
float actual_volumetric_rate() const { return actual_feedrate * mm3_per_mm; }
static const PathVertex DUMMY_PATH_VERTEX;
};
} // namespace libvgcode
#endif // VGCODE_PATHVERTEX_HPP

View File

@ -0,0 +1,218 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_TYPES_HPP
#define VGCODE_TYPES_HPP
#define VGCODE_ENABLE_COG_AND_TOOL_MARKERS 0
#include <array>
#include <vector>
#include <cstdint>
namespace libvgcode {
static constexpr float PI = 3.141592f;
//
// Predefined values for the radius, in mm, of the cylinders used to render the travel moves.
//
static constexpr float DEFAULT_TRAVELS_RADIUS_MM = 0.1f;
static constexpr float MIN_TRAVELS_RADIUS_MM = 0.05f;
static constexpr float MAX_TRAVELS_RADIUS_MM = 1.0f;
//
// Predefined values for the radius, in mm, of the cylinders used to render the wipe moves.
//
static constexpr float DEFAULT_WIPES_RADIUS_MM = 0.1f;
static constexpr float MIN_WIPES_RADIUS_MM = 0.05f;
static constexpr float MAX_WIPES_RADIUS_MM = 1.0f;
//
// Vector in 3 dimensions
// [0] -> x
// [1] -> y
// [2] -> z
// Used for positions, displacements and so on.
//
using Vec3 = std::array<float, 3>;
//
// 4x4 square matrix with elements in column-major order:
// | a[0] a[4] a[8] a[12] |
// | a[1] a[5] a[9] a[13] |
// | a[2] a[6] a[10] a[14] |
// | a[3] a[7] a[11] a[15] |
//
using Mat4x4 = std::array<float, 16>;
//
// RGB color
// [0] -> red
// [1] -> green
// [2] -> blue
//
using Color = std::array<uint8_t, 3>;
//
// Color palette
//
using Palette = std::vector<Color>;
//
// Axis aligned box in 3 dimensions
// [0] -> { min_x, min_y, min_z }
// [1] -> { max_x, max_y, max_z }
//
using AABox = std::array<Vec3, 2>;
//
// One dimensional natural numbers interval
// [0] -> min
// [1] -> max
//
using Interval = std::array<std::size_t, 2>;
//
// View types
//
enum class EViewType : uint8_t
{
FeatureType,
Height,
Width,
Speed,
ActualSpeed,
FanSpeed,
Temperature,
VolumetricFlowRate,
ActualVolumetricFlowRate,
LayerTimeLinear,
LayerTimeLogarithmic,
Tool,
ColorPrint,
COUNT
};
static constexpr std::size_t VIEW_TYPES_COUNT = static_cast<std::size_t>(EViewType::COUNT);
//
// Move types
//
enum class EMoveType : uint8_t
{
Noop,
Retract,
Unretract,
Seam,
ToolChange,
ColorChange,
PausePrint,
CustomGCode,
Travel,
Wipe,
Extrude,
COUNT
};
static constexpr std::size_t MOVE_TYPES_COUNT = static_cast<std::size_t>(EMoveType::COUNT);
//
// Extrusion roles
//
enum class EGCodeExtrusionRole : uint8_t
{
// This enum is used as in index into extrusion_roles_visibility.
// Better only add things to the end.
None,
Perimeter,
ExternalPerimeter,
OverhangPerimeter,
InternalInfill,
SolidInfill,
TopSolidInfill,
Ironing,
BridgeInfill,
GapFill,
Skirt,
SupportMaterial,
SupportMaterialInterface,
WipeTower,
Custom,
COUNT
};
static constexpr std::size_t GCODE_EXTRUSION_ROLES_COUNT = static_cast<std::size_t>(EGCodeExtrusionRole::COUNT);
//
// Option types
//
enum class EOptionType : uint8_t
{
// This enum is used as in index into options_visibility.
// Better only add things to the end.
Travels,
Wipes,
Retractions,
Unretractions,
Seams,
ToolChanges,
ColorChanges,
PausePrints,
CustomGCodes,
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
CenterOfGravity,
ToolMarker,
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
COUNT
};
static constexpr std::size_t OPTION_TYPES_COUNT = static_cast<std::size_t>(EOptionType::COUNT);
//
// Time modes
//
enum class ETimeMode : uint8_t
{
Normal,
Stealth,
COUNT
};
static constexpr std::size_t TIME_MODES_COUNT = static_cast<std::size_t>(ETimeMode::COUNT);
//
// Color range types
//
enum class EColorRangeType : uint8_t
{
Linear,
Logarithmic,
COUNT
};
static constexpr std::size_t COLOR_RANGE_TYPES_COUNT = static_cast<std::size_t>(EColorRangeType::COUNT);
//
// Predefined colors
//
static const Color DUMMY_COLOR{ 64, 64, 64 };
//
// Mapping from EMoveType to EOptionType
// Returns EOptionType::COUNT if the given move type does not correspond
// to any option type.
//
extern EOptionType move_type_to_option(EMoveType type);
//
// Returns the linear interpolation between the two given colors
// at the given t.
// t is clamped in the range [0..1]
//
extern Color lerp(const Color& c1, const Color& c2, float t);
} // namespace libvgcode
#endif // VGCODE_TYPES_HPP

View File

@ -0,0 +1,419 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_VIEWER_HPP
#define VGCODE_VIEWER_HPP
#include "Types.hpp"
#include <string>
namespace libvgcode {
class ViewerImpl;
struct GCodeInputData;
struct PathVertex;
class ColorRange;
struct ColorPrint;
class Viewer
{
public:
Viewer();
~Viewer();
Viewer(const Viewer& other) = delete;
Viewer(Viewer&& other) = delete;
Viewer& operator = (const Viewer& other) = delete;
Viewer& operator = (Viewer&& other) = delete;
//
// Initialize the viewer.
// Param opengl_context_version must be the string returned by glGetString(GL_VERSION).
// This method must be called after a valid OpenGL context has been already created
// and before calling any other method of the viewer.
// Throws an std::runtime_error exception if:
// * the method is called before creating an OpenGL context
// * the created OpenGL context does not support OpenGL 3.2 or greater
// * when using OpenGL ES, the created OpenGL ES context does not support OpenGL ES 2.0 or greater
// * any of the shaders fails to compile
//
void init(const std::string& opengl_context_version);
//
// Release the resources used by the viewer.
// This method must be called before releasing the OpenGL context if the viewer
// goes out of scope after releasing it.
//
void shutdown();
//
// Reset the contents of the viewer.
// Automatically called by load() method.
//
void reset();
//
// Setup the viewer content from the given data.
// See: GCodeInputData
//
void load(GCodeInputData&& gcode_data);
//
// Render the toolpaths according to the current settings and
// using the given camera matrices.
//
void render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
//
// ************************************************************************
// Settings
// The following methods can be used to query/customize the parameters
// used to render the toolpaths.
// ************************************************************************
//
//
// View type
// See: EViewType
//
EViewType get_view_type() const;
void set_view_type(EViewType type);
//
// Time mode
// See: ETimeMode
//
ETimeMode get_time_mode() const;
void set_time_mode(ETimeMode mode);
//
// Top layer only
// Whether or not the visible range is limited to the current top layer only.
//
bool is_top_layer_only_view_range() const;
//
// Toggle the top layer only state.
//
void toggle_top_layer_only_view_range();
//
// Returns true if the given option is visible.
//
bool is_option_visible(EOptionType type) const;
//
// Toggle the visibility state of the given option.
//
void toggle_option_visibility(EOptionType type);
//
// Returns true if the given extrusion role is visible.
//
bool is_extrusion_role_visible(EGCodeExtrusionRole role) const;
//
// Toggle the visibility state of the given extrusion role.
//
void toggle_extrusion_role_visibility(EGCodeExtrusionRole role);
//
// Return the color used to render the given extrusion rols.
//
const Color& get_extrusion_role_color(EGCodeExtrusionRole role) const;
//
// Set the color used to render the given extrusion role.
//
void set_extrusion_role_color(EGCodeExtrusionRole role, const Color& color);
//
// Reset the colors used to render the extrusion roles to the default value.
//
void reset_default_extrusion_roles_colors();
//
// Return the color used to render the given option.
//
const Color& get_option_color(EOptionType type) const;
//
// Set the color used to render the given option.
//
void set_option_color(EOptionType type, const Color& color);
//
// Reset the colors used to render the options to the default value.
//
void reset_default_options_colors();
//
// Return the count of colors in the palette used to render
// the toolpaths when the view type is EViewType::Tool.
//
size_t get_tool_colors_count() const;
//
// Return the palette used to render the toolpaths when
// the view type is EViewType::Tool.
//
const Palette& get_tool_colors() const;
//
// Set the palette used to render the toolpaths when
// the view type is EViewType::Tool with the given one.
//
void set_tool_colors(const Palette& colors);
//
// Return the count of colors in the palette used to render
// the toolpaths when the view type is EViewType::ColorPrint.
//
size_t get_color_print_colors_count() const;
//
// Return the palette used to render the toolpaths when
// the view type is EViewType::ColorPrint.
//
const Palette& get_color_print_colors() const;
//
// Set the palette used to render the toolpaths when
// the view type is EViewType::ColorPrint with the given one.
//
void set_color_print_colors(const Palette& colors);
//
// Get the color range for the given view type.
// Valid view types are:
// EViewType::Height
// EViewType::Width
// EViewType::Speed
// EViewType::ActualSpeed
// EViewType::FanSpeed
// EViewType::Temperature
// EViewType::VolumetricFlowRate
// EViewType::ActualVolumetricFlowRate
// EViewType::LayerTimeLinear
// EViewType::LayerTimeLogarithmic
//
const ColorRange& get_color_range(EViewType type) const;
//
// Set the palette for the color range corresponding to the given view type
// with the given value.
// Valid view types are:
// EViewType::Height
// EViewType::Width
// EViewType::Speed
// EViewType::ActualSpeed
// EViewType::FanSpeed
// EViewType::Temperature
// EViewType::VolumetricFlowRate
// EViewType::ActualVolumetricFlowRate
// EViewType::LayerTimeLinear
// EViewType::LayerTimeLogarithmic
//
void set_color_range_palette(EViewType type, const Palette& palette);
//
// Get the radius, in mm, of the cylinders used to render the travel moves.
//
float get_travels_radius() const;
//
// Set the radius, in mm, of the cylinders used to render the travel moves.
// Radius is clamped to [MIN_TRAVELS_RADIUS_MM..MAX_TRAVELS_RADIUS_MM]
//
void set_travels_radius(float radius);
//
// Get the radius, in mm, of the cylinders used to render the wipe moves.
//
float get_wipes_radius() const;
//
// Set the radius, in mm, of the cylinders used to render the wipe moves.
// Radius is clamped to [MIN_WIPES_RADIUS_MM..MAX_WIPES_RADIUS_MM]
//
void set_wipes_radius(float radius);
//
// Return the count of detected layers.
//
size_t get_layers_count() const;
//
// Return the current visible layers range.
//
const Interval& get_layers_view_range() const;
//
// Set the current visible layers range with the given interval.
// Values are clamped to [0..get_layers_count() - 1].
//
void set_layers_view_range(const Interval& range);
//
// Set the current visible layers range with the given min and max values.
// Values are clamped to [0..get_layers_count() - 1].
//
void set_layers_view_range(Interval::value_type min, Interval::value_type max);
//
// Return the current visible range.
// Three ranges are defined: full, enabled and visible.
// For all of them the range endpoints represent:
// [0] -> min vertex id
// [1] -> max vertex id
// Full is the range of vertices that could potentially be visualized accordingly to the current settings.
// Enabled is the part of the full range that is selected for visualization accordingly to the current settings.
// Visible is the part of the enabled range that is actually visualized accordingly to the current settings.
//
const Interval& get_view_visible_range() const;
//
// Set the current visible range.
// Values are clamped to the current view enabled range;
//
void set_view_visible_range(Interval::value_type min, Interval::value_type max);
//
// Return the current full range.
//
const Interval& get_view_full_range() const;
//
// Return the current enabled range.
//
const Interval& get_view_enabled_range() const;
//
// ************************************************************************
// Property getters
// The following methods can be used to query detected properties.
// ************************************************************************
//
//
// Spiral vase mode
// Whether or not the gcode was generated with spiral vase mode enabled.
// See: GCodeInputData
//
bool is_spiral_vase_mode() const;
//
// Return the z of the layer with the given id
// or 0.0f if the id does not belong to [0..get_layers_count() - 1].
//
float get_layer_z(size_t layer_id) const;
//
// Return the list of zs of the detected layers.
//
std::vector<float> get_layers_zs() const;
//
// Return the id of the layer closest to the given z.
//
size_t get_layer_id_at(float z) const;
//
// Return the count of detected used extruders.
//
size_t get_used_extruders_count() const;
//
// Return the list of ids of the detected used extruders.
//
std::vector<uint8_t> get_used_extruders_ids() const;
//
// Return the list of detected time modes.
//
std::vector<ETimeMode> get_time_modes() const;
//
// Return the count of vertices used to render the toolpaths
//
size_t get_vertices_count() const;
//
// Return the vertex pointed by the max value of the view visible range
//
const PathVertex& get_current_vertex() const;
//
// Return the index of vertex pointed by the max value of the view visible range
//
size_t get_current_vertex_id() const;
//
// Return the vertex at the given index
//
const PathVertex& get_vertex_at(size_t id) const;
//
// Return the total estimated time, in seconds, using the current time mode.
//
float get_estimated_time() const;
//
// Return the estimated time, in seconds, at the vertex with the given index
// using the current time mode.
//
float get_estimated_time_at(size_t id) const;
//
// Return the color used to render the given vertex with the current settings.
//
Color get_vertex_color(const PathVertex& vertex) const;
//
// Return the count of detected extrusion roles
//
size_t get_extrusion_roles_count() const;
//
// Return the list of detected extrusion roles
//
std::vector<EGCodeExtrusionRole> get_extrusion_roles() const;
//
// Return the count of detected options.
//
size_t get_options_count() const;
//
// Return the list of detected options.
//
const std::vector<EOptionType>& get_options() const;
//
// Return the count of detected color prints.
//
size_t get_color_prints_count(uint8_t extruder_id) const;
//
// Return the list of detected color prints.
//
std::vector<ColorPrint> get_color_prints(uint8_t extruder_id) const;
//
// Return the estimated time for the given role and the current time mode.
//
float get_extrusion_role_estimated_time(EGCodeExtrusionRole role) const;
//
// Return the estimated time for the travel moves and the current time mode.
//
float get_travels_estimated_time() const;
//
// Return the list of layers time for the current time mode.
//
std::vector<float> get_layers_estimated_times() const;
//
// Return the axes aligned bounding box containing all the given types.
//
AABox get_bounding_box(const std::vector<EMoveType>& types = {
EMoveType::Retract, EMoveType::Unretract, EMoveType::Seam, EMoveType::ToolChange,
EMoveType::ColorChange, EMoveType::PausePrint, EMoveType::CustomGCode, EMoveType::Travel,
EMoveType::Wipe, EMoveType::Extrude }) const;
//
// Return the axes aligned bounding box containing all the extrusions with the given roles.
//
AABox get_extrusion_bounding_box(const std::vector<EGCodeExtrusionRole>& roles = {
EGCodeExtrusionRole::Perimeter, EGCodeExtrusionRole::ExternalPerimeter, EGCodeExtrusionRole::OverhangPerimeter,
EGCodeExtrusionRole::InternalInfill, EGCodeExtrusionRole::SolidInfill, EGCodeExtrusionRole::TopSolidInfill,
EGCodeExtrusionRole::Ironing, EGCodeExtrusionRole::BridgeInfill, EGCodeExtrusionRole::GapFill,
EGCodeExtrusionRole::Skirt, EGCodeExtrusionRole::SupportMaterial, EGCodeExtrusionRole::SupportMaterialInterface,
EGCodeExtrusionRole::WipeTower, EGCodeExtrusionRole::Custom }) const;
//
// Return the size of the used cpu memory, in bytes
//
size_t get_used_cpu_memory() const;
//
// Return the size of the used gpu memory, in bytes
//
size_t get_used_gpu_memory() const;
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Returns the position of the center of gravity of the toolpaths.
// It does not take in account extrusions of type:
// Skirt
// Support Material
// Support Material Interface
// WipeTower
// Custom
//
Vec3 get_cog_position() const;
float get_cog_marker_scale_factor() const;
void set_cog_marker_scale_factor(float factor);
const Vec3& get_tool_marker_position() const;
float get_tool_marker_offset_z() const;
void set_tool_marker_offset_z(float offset_z);
float get_tool_marker_scale_factor() const;
void set_tool_marker_scale_factor(float factor);
const Color& get_tool_marker_color() const;
void set_tool_marker_color(const Color& color);
float get_tool_marker_alpha() const;
void set_tool_marker_alpha(float alpha);
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
private:
ViewerImpl* m_impl{ nullptr };
};
} // namespace libvgcode
#endif // VGCODE_VIEWER_HPP

View File

@ -0,0 +1,8 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "Bitset.hpp"
namespace libvgcode {
} // namespace libvgcode

View File

@ -0,0 +1,103 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_BITSET_HPP
#define VGCODE_BITSET_HPP
#include <atomic>
#include <vector>
namespace libvgcode {
// By default, types are not atomic,
template<typename T> auto constexpr is_atomic = false;
// but std::atomic<T> types are,
template<typename T> auto constexpr is_atomic<std::atomic<T>> = true;
template<typename T = unsigned long long>
struct BitSet
{
BitSet() = default;
BitSet(std::size_t size) : size(size), blocks(1 + (size / (sizeof(T) * 8))) { clear(); }
void clear() {
for (std::size_t i = 0; i < blocks.size(); ++i) {
blocks[i] &= T(0);
}
}
void setAll() {
for (std::size_t i = 0; i < blocks.size(); ++i) {
blocks[i] |= ~T(0);
}
}
//return true if bit changed
bool set(std::size_t index) {
const auto [block_idx, bit_idx] = get_coords(index);
const T mask = (T(1) << bit_idx);
bool flip = mask ^ blocks[block_idx];
blocks[block_idx] |= mask;
return flip;
}
//return true if bit changed
bool reset(std::size_t index) {
const auto [block_idx, bit_idx] = get_coords(index);
const T mask = (T(1) << bit_idx);
const bool flip = mask ^ blocks[block_idx];
blocks[block_idx] &= (~mask);
return flip;
}
bool operator [] (std::size_t index) const {
const auto [block_idx, bit_idx] = get_coords(index);
return ((blocks[block_idx] >> bit_idx) & 1) != 0;
}
template<typename U>
BitSet& operator &= (const BitSet<U>& other) {
static_assert(sizeof(T) == sizeof(U), "Type1 and Type2 must be of the same size.");
for (std::size_t i = 0; i < blocks.size(); ++i) {
blocks[i] &= other.blocks[i];
}
return *this;
}
// Atomic set operation (enabled only for atomic types), return true if bit changed
template<typename U = T>
inline typename std::enable_if<is_atomic<U>, bool>::type set_atomic(std::size_t index) {
const auto [block_idx, bit_idx] = get_coords(index);
const T mask = static_cast<T>(1) << bit_idx;
const T oldval = blocks[block_idx].fetch_or(mask, std::memory_order_relaxed);
return oldval ^ (oldval or mask);
}
// Atomic reset operation (enabled only for atomic types), return true if bit changed
template<typename U = T>
inline typename std::enable_if<is_atomic<U>, bool>::type reset_atomic(std::size_t index) {
const auto [block_idx, bit_idx] = get_coords(index);
const T mask = ~(static_cast<T>(1) << bit_idx);
const T oldval = blocks[block_idx].fetch_and(mask, std::memory_order_relaxed);
return oldval ^ (oldval and mask);
}
std::pair<std::size_t, std::size_t> get_coords(std::size_t index) const {
const std::size_t block_idx = index / (sizeof(T) * 8);
const std::size_t bit_idx = index % (sizeof(T) * 8);
return { block_idx, bit_idx };
}
std::size_t size_in_bytes_cpu() const {
return blocks.size() * sizeof(T);
}
std::size_t size{ 0 };
std::vector<T> blocks{ 0 };
};
} // namespace libvgcode
#endif // VGCODE_BITSET_HPP

View File

@ -0,0 +1,173 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
// needed for tech VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include "../include/Types.hpp"
#include "CogMarker.hpp"
#include "OpenGLUtils.hpp"
#include "Utils.hpp"
#include <cmath>
#include <assert.h>
#include <algorithm>
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
namespace libvgcode {
// Geometry:
// sphere with 'resolution' sides, centered at (0.0, 0.0, 0.0) and radius equal to 'radius'
void CogMarker::init(uint8_t resolution, float radius)
{
if (m_vao_id != 0)
return;
// ensure vertices count does not exceed 65536
resolution = std::clamp<uint8_t>(resolution, 4, 105);
const uint16_t sector_count = (uint16_t)resolution;
const uint16_t stack_count = (uint16_t)resolution;
const float sector_step = 2.0f * PI / float(sector_count);
const float stack_step = PI / float(stack_count);
std::vector<float> vertices;
const uint16_t vertices_count = (stack_count - 1) * sector_count + 2;
vertices.reserve(6 * vertices_count);
m_indices_count = 3 * (2 * (stack_count - 1) * sector_count);
std::vector<uint16_t> indices;
indices.reserve(m_indices_count);
// vertices
for (uint16_t i = 0; i <= stack_count; ++i) {
// from pi/2 to -pi/2
const float stack_angle = 0.5f * PI - stack_step * float(i);
const float xy = radius * std::cos(stack_angle);
const float z = radius * std::sin(stack_angle);
if (i == 0 || i == stack_count) {
const Vec3 pos = { xy, 0.0f, z };
const Vec3 norm = normalize(pos);
add_vertex(pos, norm, vertices);
}
else {
for (uint16_t j = 0; j < sector_count; ++j) {
// from 0 to 2pi
const float sector_angle = sector_step * float(j);
const Vec3 pos = { xy * std::cos(sector_angle), xy * std::sin(sector_angle), z };
const Vec3 norm = normalize(pos);
add_vertex(pos, norm, vertices);
}
}
}
// indices
for (uint16_t i = 0; i < stack_count; ++i) {
// Beginning of current stack.
uint16_t k1 = (i == 0) ? 0 : (1 + (i - 1) * sector_count);
const uint16_t k1_first = k1;
// Beginning of next stack.
uint16_t k2 = (i == 0) ? 1 : (k1 + sector_count);
const uint16_t k2_first = k2;
for (uint16_t j = 0; j < sector_count; ++j) {
// 2 triangles per sector excluding first and last stacks
uint16_t k1_next = k1;
uint16_t k2_next = k2;
if (i != 0) {
k1_next = (j + 1 == sector_count) ? k1_first : (k1 + 1);
add_triangle(k1, k2, k1_next, indices);
}
if (i + 1 != stack_count) {
k2_next = (j + 1 == sector_count) ? k2_first : (k2 + 1);
add_triangle(k1_next, k2, k2_next, indices);
}
k1 = k1_next;
k2 = k2_next;
}
}
m_size_in_bytes_gpu += vertices.size() * sizeof(float);
m_size_in_bytes_gpu += indices.size() * sizeof(uint16_t);
const size_t vertex_stride = 6 * sizeof(float);
const size_t position_offset = 0;
const size_t normal_offset = 3 * sizeof(float);
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
int curr_array_buffer;
glsafe(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &curr_array_buffer));
glsafe(glGenVertexArrays(1, &m_vao_id));
glsafe(glBindVertexArray(m_vao_id));
glsafe(glGenBuffers(1, &m_vbo_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
glsafe(glEnableVertexAttribArray(0));
glsafe(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)position_offset));
glsafe(glEnableVertexAttribArray(1));
glsafe(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)normal_offset));
glsafe(glGenBuffers(1, &m_ibo_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.data(), GL_STATIC_DRAW));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, curr_array_buffer));
glsafe(glBindVertexArray(curr_vertex_array));
}
void CogMarker::shutdown()
{
if (m_ibo_id != 0) {
glsafe(glDeleteBuffers(1, &m_ibo_id));
m_ibo_id = 0;
}
if (m_vbo_id != 0) {
glsafe(glDeleteBuffers(1, &m_vbo_id));
m_vbo_id = 0;
}
if (m_vao_id != 0) {
glsafe(glDeleteVertexArrays(1, &m_vao_id));
m_vao_id = 0;
}
m_size_in_bytes_gpu = 0;
}
void CogMarker::render()
{
if (m_vao_id == 0 || m_vbo_id == 0 || m_ibo_id == 0 || m_indices_count == 0)
return;
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
glcheck();
glsafe(glBindVertexArray(m_vao_id));
glsafe(glDrawElements(GL_TRIANGLES, m_indices_count, GL_UNSIGNED_SHORT, (const void*)0));
glsafe(glBindVertexArray(curr_vertex_array));
}
void CogMarker::update(const Vec3& position, float mass)
{
m_total_position = m_total_position + mass * position;
m_total_mass += mass;
}
void CogMarker::reset()
{
m_total_position = { 0.0f, 0.0f, 0.0f };
m_total_mass = 0.0f;
}
Vec3 CogMarker::get_position() const
{
assert(m_total_mass > 0.0f);
const float inv_total_mass = 1.0f / m_total_mass;
return inv_total_mass * m_total_position;
}
} // namespace libvgcode
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS

View File

@ -0,0 +1,77 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_COGMARKER_HPP
#define VGCODE_COGMARKER_HPP
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
namespace libvgcode {
class CogMarker
{
public:
CogMarker() = default;
~CogMarker() { shutdown(); }
CogMarker(const CogMarker& other) = delete;
CogMarker(CogMarker&& other) = delete;
CogMarker& operator = (const CogMarker& other) = delete;
CogMarker& operator = (CogMarker&& other) = delete;
//
// Initialize gpu buffers
//
void init(uint8_t resolution, float radius);
//
// Release gpu buffers
//
void shutdown();
//
// Render the marker
//
void render();
//
// Update values used to calculate the center of gravity
//
void update(const Vec3& position, float mass);
//
// Reset values used to calculate the center of gravity
//
void reset();
//
// Return the calculated center of gravity position
//
Vec3 get_position() const;
//
// Return the size of the data sent to gpu, in bytes.
//
size_t size_in_bytes_gpu() const { return m_size_in_bytes_gpu; }
private:
//
// Values used to calculate the center of gravity
//
float m_total_mass{ 0.0f };
Vec3 m_total_position{ 0.0f, 0.0f, 0.0f };
//
// The count of indices stored into the ibo buffer.
//
uint16_t m_indices_count{ 0 };
//
// gpu buffers ids.
//
unsigned int m_vao_id{ 0 };
unsigned int m_vbo_id{ 0 };
unsigned int m_ibo_id{ 0 };
//
// Size of the data sent to gpu, in bytes.
//
size_t m_size_in_bytes_gpu{ 0 };
};
} // namespace libvgcode
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // VGCODE_COGMARKER_HPP

View File

@ -0,0 +1,8 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/ColorPrint.hpp"
namespace libvgcode {
} // namespace libvgcode

View File

@ -0,0 +1,139 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/ColorRange.hpp"
#include "Utils.hpp"
#include <algorithm>
#include <assert.h>
#include <cmath>
namespace libvgcode {
const ColorRange ColorRange::DUMMY_COLOR_RANGE = ColorRange();
static float get_step_size(const ColorRange& color_range)
{
const std::array<float, 2>& range = color_range.get_range();
const Palette& palette = color_range.get_palette();
switch (color_range.get_type())
{
default:
case EColorRangeType::Linear:
{
return (range[1] - range[0]) / (static_cast<float>(palette.size()) - 1.0f);
}
case EColorRangeType::Logarithmic:
{
return (range[0] != 0.0f) ? std::log(range[1] / range[0]) / (static_cast<float>(palette.size()) - 1.0f) : 0.0f;
}
}
}
ColorRange::ColorRange(EColorRangeType type)
: m_type(type)
, m_palette(DEFAULT_RANGES_COLORS)
{
}
EColorRangeType ColorRange::get_type() const
{
return m_type;
}
const Palette& ColorRange::get_palette() const
{
return m_palette;
}
void ColorRange::set_palette(const Palette& palette)
{
if (palette.size() > 1)
m_palette = palette;
}
Color ColorRange::get_color_at(float value) const
{
// Input value scaled to the colors range
float global_t = 0.0f;
value = std::clamp(value, m_range[0], m_range[1]);
const float step = get_step_size(*this);
if (step > 0.0f) {
if (m_type == EColorRangeType::Logarithmic) {
if (m_range[0] != 0.0f)
global_t = std::log(value / m_range[0]) / step;
}
else
global_t = (value - m_range[0]) / step;
}
const size_t color_max_idx = m_palette.size() - 1;
// Compute the two colors just below (low) and above (high) the input value
const size_t color_low_idx = std::clamp<size_t>(static_cast<size_t>(global_t), 0, color_max_idx);
const size_t color_high_idx = std::clamp<size_t>(color_low_idx + 1, 0, color_max_idx);
// Interpolate between the low and high colors to find exactly which color the input value should get
return lerp(m_palette[color_low_idx], m_palette[color_high_idx], global_t - static_cast<float>(color_low_idx));
}
const std::array<float, 2>& ColorRange::get_range() const
{
return m_range;
}
std::vector<float> ColorRange::get_values() const
{
std::vector<float> ret;
if (m_count == 1) {
// single item use case
ret.emplace_back(m_range[0]);
}
else if (m_count == 2) {
// two items use case
ret.emplace_back(m_range[0]);
ret.emplace_back(m_range[1]);
}
else {
const float step_size = get_step_size(*this);
for (size_t i = 0; i < m_palette.size(); ++i) {
float value = 0.0f;
switch (m_type)
{
default:
case EColorRangeType::Linear: { value = m_range[0] + static_cast<float>(i) * step_size; break; }
case EColorRangeType::Logarithmic: { value = ::exp(::log(m_range[0]) + static_cast<float>(i) * step_size); break; }
}
ret.emplace_back(value);
}
}
return ret;
}
size_t ColorRange::size_in_bytes_cpu() const
{
size_t ret = STDVEC_MEMSIZE(m_palette, Color);
return ret;
}
void ColorRange::update(float value)
{
if (value != m_range[0] && value != m_range[1])
++m_count;
m_range[0] = std::min(m_range[0], value);
m_range[1] = std::max(m_range[1], value);
}
void ColorRange::reset()
{
m_range = { FLT_MAX, -FLT_MAX };
m_count = 0;
}
} // namespace libvgcode

View File

@ -0,0 +1,39 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "ExtrusionRoles.hpp"
namespace libvgcode {
void ExtrusionRoles::add(EGCodeExtrusionRole role, const std::array<float, TIME_MODES_COUNT>& times)
{
auto role_it = m_items.find(role);
if (role_it == m_items.end())
role_it = m_items.insert(std::make_pair(role, Item())).first;
for (std::size_t i = 0; i < TIME_MODES_COUNT; ++i) {
role_it->second.times[i] += times[i];
}
}
std::vector<EGCodeExtrusionRole> ExtrusionRoles::get_roles() const
{
std::vector<EGCodeExtrusionRole> ret;
ret.reserve(m_items.size());
for (const auto& [role, item] : m_items) {
ret.emplace_back(role);
}
return ret;
}
float ExtrusionRoles::get_time(EGCodeExtrusionRole role, ETimeMode mode) const
{
const auto role_it = m_items.find(role);
if (role_it == m_items.end())
return 0.0f;
return (mode < ETimeMode::COUNT) ? role_it->second.times[static_cast<std::size_t>(mode)] : 0.0f;
}
} // namespace libvgcode

View File

@ -0,0 +1,36 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_EXTRUSION_ROLES_HPP
#define VGCODE_EXTRUSION_ROLES_HPP
#include "../include/Types.hpp"
#include <map>
namespace libvgcode {
class ExtrusionRoles
{
public:
struct Item
{
std::array<float, TIME_MODES_COUNT> times;
};
void add(EGCodeExtrusionRole role, const std::array<float, TIME_MODES_COUNT>& times);
std::size_t get_roles_count() const { return m_items.size(); }
std::vector<EGCodeExtrusionRole> get_roles() const;
float get_time(EGCodeExtrusionRole role, ETimeMode mode) const;
void reset() { m_items.clear(); }
private:
std::map<EGCodeExtrusionRole, Item> m_items;
};
} // namespace libvgcode
#endif // VGCODE_EXTRUSION_ROLES_HPP

View File

@ -0,0 +1,8 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/GCodeInputData.hpp"
namespace libvgcode {
} // namespace libvgcode

View File

@ -0,0 +1,83 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "Layers.hpp"
#include "../include/PathVertex.hpp"
#include "Utils.hpp"
#include <assert.h>
#include <algorithm>
namespace libvgcode {
static bool is_colorprint_option(const PathVertex& v)
{
return v.type == EMoveType::PausePrint || v.type == EMoveType::CustomGCode;
}
void Layers::update(const PathVertex& vertex, uint32_t vertex_id)
{
if (m_items.empty() || vertex.layer_id == m_items.size()) {
// this code assumes that gcode paths are sent sequentially, one layer after the other
assert(vertex.layer_id == static_cast<uint32_t>(m_items.size()));
Item& item = m_items.emplace_back(Item());
if (vertex.type == EMoveType::Extrude && vertex.role != EGCodeExtrusionRole::Custom)
item.z = vertex.position[2];
item.range.set(vertex_id, vertex_id);
item.times = vertex.times;
item.contains_colorprint_options |= is_colorprint_option(vertex);
}
else {
Item& item = m_items.back();
if (vertex.type == EMoveType::Extrude && vertex.role != EGCodeExtrusionRole::Custom && item.z != vertex.position[2])
item.z = vertex.position[2];
item.range.set_max(vertex_id);
for (size_t i = 0; i < TIME_MODES_COUNT; ++i) {
item.times[i] += vertex.times[i];
}
item.contains_colorprint_options |= is_colorprint_option(vertex);
}
}
void Layers::reset()
{
m_items.clear();
m_view_range.reset();
}
std::vector<float> Layers::get_times(ETimeMode mode) const
{
std::vector<float> ret;
if (mode < ETimeMode::COUNT) {
for (const Item& item : m_items) {
ret.emplace_back(item.times[static_cast<size_t>(mode)]);
}
}
return ret;
}
std::vector<float> Layers::get_zs() const
{
std::vector<float> ret;
ret.reserve(m_items.size());
for (const Item& item : m_items) {
ret.emplace_back(item.z);
}
return ret;
}
size_t Layers::get_layer_id_at(float z) const
{
auto iter = std::upper_bound(m_items.begin(), m_items.end(), z, [](float z, const Item& item) { return item.z < z; });
return std::distance(m_items.begin(), iter);
}
size_t Layers::size_in_bytes_cpu() const
{
size_t ret = STDVEC_MEMSIZE(m_items, Item);
return ret;
}
} // namespace libvgcode

View File

@ -0,0 +1,60 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_LAYERS_HPP
#define VGCODE_LAYERS_HPP
#include "Range.hpp"
namespace libvgcode {
struct PathVertex;
class Layers
{
public:
void update(const PathVertex& vertex, uint32_t vertex_id);
void reset();
bool empty() const { return m_items.empty(); }
std::size_t count() const { return m_items.size(); }
std::vector<float> get_times(ETimeMode mode) const;
std::vector<float> get_zs() const;
float get_layer_time(ETimeMode mode, std::size_t layer_id) const {
return (mode < ETimeMode::COUNT&& layer_id < m_items.size()) ?
m_items[layer_id].times[static_cast<std::size_t>(mode)] : 0.0f;
}
float get_layer_z(std::size_t layer_id) const {
return (layer_id < m_items.size()) ? m_items[layer_id].z : 0.0f;
}
std::size_t get_layer_id_at(float z) const;
const Interval& get_view_range() const { return m_view_range.get(); }
void set_view_range(const Interval& range) { set_view_range(range[0], range[1]); }
void set_view_range(Interval::value_type min, Interval::value_type max) { m_view_range.set(min, max); }
bool layer_contains_colorprint_options(std::size_t layer_id) const {
return (layer_id < m_items.size()) ? m_items[layer_id].contains_colorprint_options : false;
}
std::size_t size_in_bytes_cpu() const;
private:
struct Item
{
float z{ 0.0f };
Range range;
std::array<float, TIME_MODES_COUNT> times{ 0.0f, 0.0f };
bool contains_colorprint_options{ false };
};
std::vector<Item> m_items;
Range m_view_range;
};
} // namespace libvgcode
#endif // VGCODE_LAYERS_HPP

View File

@ -0,0 +1,98 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak, Vojtěch Bubník @bubnikv
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "OpenGLUtils.hpp"
#include <iostream>
#include <assert.h>
#include <cctype>
#include <stdio.h>
#include <cstring>
namespace libvgcode {
#ifdef HAS_GLSAFE
void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name)
{
const GLenum err = glGetError();
if (err == GL_NO_ERROR)
return;
const char* sErr = 0;
switch (err) {
case GL_INVALID_ENUM: { sErr = "Invalid Enum"; break; }
case GL_INVALID_VALUE: { sErr = "Invalid Value"; break; }
// be aware that GL_INVALID_OPERATION is generated if glGetError is executed between the execution of glBegin / glEnd
case GL_INVALID_OPERATION: { sErr = "Invalid Operation"; break; }
case GL_OUT_OF_MEMORY: { sErr = "Out Of Memory"; break; }
case GL_INVALID_FRAMEBUFFER_OPERATION: { sErr = "Invalid framebuffer operation"; break; }
#if !defined(ENABLE_OPENGL_ES)
case GL_STACK_OVERFLOW: { sErr = "Stack Overflow"; break; }
case GL_STACK_UNDERFLOW: { sErr = "Stack Underflow"; break; }
#endif // ENABLE_OPENGL_ES
default: { sErr = "Unknown"; break; }
}
std::cout << "OpenGL error in " << file_name << ":" << line << ", function " << function_name << "() : " << (int)err << " - " << sErr << "\n";
assert(false);
}
#endif // HAS_GLSAFE
static const char* OPENGL_ES_PREFIXES[] = { "OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES ", nullptr };
bool OpenGLWrapper::s_valid_context = false;
#ifdef ENABLE_OPENGL_ES
int OpenGLWrapper::s_max_texture_size = 0;
#endif // ENABLE_OPENGL_ES
bool OpenGLWrapper::load_opengl(const std::string& context_version)
{
s_valid_context = false;
const char* version = context_version.c_str();
for (int i = 0; OPENGL_ES_PREFIXES[i] != nullptr; ++i) {
const size_t length = strlen(OPENGL_ES_PREFIXES[i]);
if (strncmp(version, OPENGL_ES_PREFIXES[i], length) == 0) {
version += length;
break;
}
}
GLint major = 0;
GLint minor = 0;
#ifdef _MSC_VER
const int res = sscanf_s(version, "%d.%d", &major, &minor);
#else
const int res = sscanf(version, "%d.%d", &major, &minor);
#endif // _MSC_VER
if (res != 2)
return false;
#ifdef ENABLE_OPENGL_ES
s_valid_context = major > 3 || (major == 3 && minor >= 0);
const int glad_res = gladLoaderLoadGLES2();
#else
s_valid_context = major > 3 || (major == 3 && minor >= 2);
const int glad_res = gladLoaderLoadGL();
#endif // ENABLE_OPENGL_ES
if (glad_res == 0)
return false;
#ifdef ENABLE_OPENGL_ES
glsafe(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_max_texture_size));
#endif // ENABLE_OPENGL_ES
return s_valid_context;
}
void OpenGLWrapper::unload_opengl()
{
#ifdef ENABLE_OPENGL_ES
gladLoaderUnloadGLES2();
#else
gladLoaderUnloadGL();
#endif // ENABLE_OPENGL_ES
}
} // namespace libvgcode

View File

@ -0,0 +1,52 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak, Vojtěch Bubník @bubnikv
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_OPENGLUTILS_HPP
#define VGCODE_OPENGLUTILS_HPP
// OpenGL loader
#ifdef ENABLE_OPENGL_ES
#include "../glad/include/glad/gles2.h"
#else
#include "../glad/include/glad/gl.h"
#endif // ENABLE_OPENGL_ES
#include <string>
namespace libvgcode {
#ifndef NDEBUG
#define HAS_GLSAFE
#endif // NDEBUG
#ifdef HAS_GLSAFE
extern void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name);
inline void glAssertRecentCall() { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); }
#define glsafe(cmd) do { cmd; glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); } while (false)
#define glcheck() do { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); } while (false)
#else
inline void glAssertRecentCall() { }
#define glsafe(cmd) cmd
#define glcheck()
#endif // HAS_GLSAFE
class OpenGLWrapper
{
public:
static bool load_opengl(const std::string& context_version);
static void unload_opengl();
static bool is_valid_context() { return s_valid_context; }
#ifdef ENABLE_OPENGL_ES
static size_t max_texture_size() { return static_cast<size_t>(s_max_texture_size); }
#endif // ENABLE_OPENGL_ES
private:
static bool s_valid_context;
#ifdef ENABLE_OPENGL_ES
static int s_max_texture_size;
#endif // ENABLE_OPENGL_ES
};
} // namespace libvgcode
#endif // VGCODE_OPENGLUTILS_HPP

View File

@ -0,0 +1,126 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "OptionTemplate.hpp"
#include "OpenGLUtils.hpp"
#include "Utils.hpp"
#include <vector>
#include <algorithm>
#include <cmath>
namespace libvgcode {
// Geometry:
// diamond with 'resolution' sides, centered at (0.0, 0.0, 0.0)
// height and width of the diamond are equal to 1.0
void OptionTemplate::init(uint8_t resolution)
{
if (m_top_vao_id != 0)
return;
m_resolution = std::max<uint8_t>(resolution, 3);
m_vertices_count = 2 + resolution;
const float step = 2.0f * PI / float(m_resolution);
//
// top fan
//
std::vector<float> top_vertices;
top_vertices.reserve(6 * m_vertices_count);
add_vertex({ 0.0f, 0.0f, 0.5f }, { 0.0f, 0.0f, 1.0f }, top_vertices);
for (uint8_t i = 0; i <= m_resolution; ++i) {
const float ii = float(i) * step;
const Vec3 pos = { 0.5f * std::cos(ii), 0.5f * std::sin(ii), 0.0f };
const Vec3 norm = normalize(pos);
add_vertex(pos, norm, top_vertices);
}
//
// bottom fan
//
std::vector<float> bottom_vertices;
bottom_vertices.reserve(6 * m_vertices_count);
add_vertex({ 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, -1.0f }, bottom_vertices);
for (uint8_t i = 0; i <= m_resolution; ++i) {
const float ii = -float(i) * step;
const Vec3 pos = { 0.5f * std::cos(ii), 0.5f * std::sin(ii), 0.0f };
const Vec3 norm = normalize(pos);
add_vertex(pos, norm, bottom_vertices);
}
m_size_in_bytes_gpu += top_vertices.size() * sizeof(float);
m_size_in_bytes_gpu += bottom_vertices.size() * sizeof(float);
const size_t vertex_stride = 6 * sizeof(float);
const size_t position_offset = 0;
const size_t normal_offset = 3 * sizeof(float);
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
int curr_array_buffer;
glsafe(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &curr_array_buffer));
glsafe(glGenVertexArrays(1, &m_top_vao_id));
glsafe(glBindVertexArray(m_top_vao_id));
glsafe(glGenBuffers(1, &m_top_vbo_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, m_top_vbo_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, top_vertices.size() * sizeof(float), top_vertices.data(), GL_STATIC_DRAW));
glsafe(glEnableVertexAttribArray(0));
glsafe(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)position_offset));
glsafe(glEnableVertexAttribArray(1));
glsafe(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)normal_offset));
glsafe(glGenVertexArrays(1, &m_bottom_vao_id));
glsafe(glBindVertexArray(m_bottom_vao_id));
glsafe(glGenBuffers(1, &m_bottom_vbo_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, m_bottom_vbo_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, bottom_vertices.size() * sizeof(float), bottom_vertices.data(), GL_STATIC_DRAW));
glsafe(glEnableVertexAttribArray(0));
glsafe(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)position_offset));
glsafe(glEnableVertexAttribArray(1));
glsafe(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)normal_offset));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, curr_array_buffer));
glsafe(glBindVertexArray(curr_vertex_array));
}
void OptionTemplate::shutdown()
{
if (m_bottom_vbo_id != 0) {
glsafe(glDeleteBuffers(1, &m_bottom_vbo_id));
m_bottom_vbo_id = 0;
}
if (m_bottom_vao_id != 0) {
glsafe(glDeleteVertexArrays(1, &m_bottom_vao_id));
m_bottom_vao_id = 0;
}
if (m_top_vbo_id != 0) {
glsafe(glDeleteBuffers(1, &m_top_vbo_id));
m_top_vbo_id = 0;
}
if (m_top_vao_id != 0) {
glsafe(glDeleteVertexArrays(1, &m_top_vao_id));
m_top_vao_id = 0;
}
m_size_in_bytes_gpu = 0;
}
void OptionTemplate::render(size_t count)
{
if (m_top_vao_id == 0 || m_top_vbo_id == 0 || m_bottom_vao_id == 0 || m_bottom_vbo_id == 0 || count == 0)
return;
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
glsafe(glBindVertexArray(m_top_vao_id));
glsafe(glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(m_vertices_count), static_cast<GLsizei>(count)));
glsafe(glBindVertexArray(m_bottom_vao_id));
glsafe(glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(m_vertices_count), static_cast<GLsizei>(count)));
glsafe(glBindVertexArray(curr_vertex_array));
}
} // namespace libvgcode

View File

@ -0,0 +1,56 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_OPTIONTEMPLATE_HPP
#define VGCODE_OPTIONTEMPLATE_HPP
#include <cstdint>
#include <cstddef>
namespace libvgcode {
class OptionTemplate
{
public:
OptionTemplate() = default;
~OptionTemplate() { shutdown(); }
OptionTemplate(const OptionTemplate& other) = delete;
OptionTemplate(OptionTemplate&& other) = delete;
OptionTemplate& operator = (const OptionTemplate& other) = delete;
OptionTemplate& operator = (OptionTemplate&& other) = delete;
//
// Initialize gpu buffers.
//
void init(uint8_t resolution);
//
// Release gpu buffers.
//
void shutdown();
void render(size_t count);
//
// Return the size of the data sent to gpu, in bytes.
//
size_t size_in_bytes_gpu() const { return m_size_in_bytes_gpu; }
private:
uint8_t m_resolution{ 0 };
uint8_t m_vertices_count{ 0 };
//
// gpu buffers ids.
//
unsigned int m_top_vao_id{ 0 };
unsigned int m_top_vbo_id{ 0 };
unsigned int m_bottom_vao_id{ 0 };
unsigned int m_bottom_vbo_id{ 0 };
//
// Size of the data sent to gpu, in bytes.
//
size_t m_size_in_bytes_gpu{ 0 };
};
} // namespace libvgcode
#endif // VGCODE_OPTIONTEMPLATE_HPP

View File

@ -0,0 +1,52 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/PathVertex.hpp"
namespace libvgcode {
const PathVertex PathVertex::DUMMY_PATH_VERTEX = PathVertex();
bool PathVertex::is_extrusion() const
{
return type == EMoveType::Extrude;
}
bool PathVertex::is_travel() const
{
return type == EMoveType::Travel;
}
bool PathVertex::is_wipe() const
{
return type == EMoveType::Wipe;
}
bool PathVertex::is_option() const
{
switch (type)
{
case EMoveType::Retract:
case EMoveType::Unretract:
case EMoveType::Seam:
case EMoveType::ToolChange:
case EMoveType::ColorChange:
case EMoveType::PausePrint:
case EMoveType::CustomGCode:
{
return true;
}
default:
{
return false;
}
}
}
bool PathVertex::is_custom_gcode() const
{
return type == EMoveType::Extrude && role == EGCodeExtrusionRole::Custom;
}
} // namespace libvgcode

View File

@ -0,0 +1,25 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "Range.hpp"
#include <algorithm>
namespace libvgcode {
void Range::set(Interval::value_type min, Interval::value_type max)
{
if (max < min)
std::swap(min, max);
m_range[0] = min;
m_range[1] = max;
}
void Range::clamp(Range& other)
{
other.m_range[0] = std::clamp(other.m_range[0], m_range[0], m_range[1]);
other.m_range[1] = std::clamp(other.m_range[1], m_range[0], m_range[1]);
}
} // namespace libvgcode

View File

@ -0,0 +1,39 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_RANGE_HPP
#define VGCODE_RANGE_HPP
#include "../include/Types.hpp"
namespace libvgcode {
class Range
{
public:
const Interval& get() const { return m_range; }
void set(const Range& other) { m_range = other.m_range; }
void set(const Interval& range) { set(range[0], range[1]); }
void set(Interval::value_type min, Interval::value_type max);
Interval::value_type get_min() const { return m_range[0]; }
void set_min(Interval::value_type min) { set(min, m_range[1]); }
Interval::value_type get_max() const { return m_range[1]; }
void set_max(Interval::value_type max) { set(m_range[0], max); }
// clamp the given range to stay inside this range
void clamp(Range& other);
void reset() { m_range = { 0, 0 }; }
bool operator == (const Range& other) const { return m_range == other.m_range; }
bool operator != (const Range& other) const { return m_range != other.m_range; }
private:
Interval m_range{ 0, 0 };
};
} // namespace libvgcode
#endif // VGCODE_RANGE_HPP

View File

@ -0,0 +1,85 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "SegmentTemplate.hpp"
#include "OpenGLUtils.hpp"
#include <cstdint>
#include <array>
namespace libvgcode {
//| /1-------6\ |
//| / | | \ |
//| 2--0-------5--7 |
//| \ | | / |
//| 3-------4 |
static constexpr const std::array<uint8_t, 24> VERTEX_DATA = {
0, 1, 2, // front spike
0, 2, 3, // front spike
0, 3, 4, // right/bottom body
0, 4, 5, // right/bottom body
0, 5, 6, // left/top body
0, 6, 1, // left/top body
5, 4, 7, // back spike
5, 7, 6, // back spike
};
void SegmentTemplate::init()
{
if (m_vao_id != 0)
return;
m_size_in_bytes_gpu += VERTEX_DATA.size() * sizeof(uint8_t);
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
int curr_array_buffer;
glsafe(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &curr_array_buffer));
glsafe(glGenVertexArrays(1, &m_vao_id));
glsafe(glBindVertexArray(m_vao_id));
glsafe(glGenBuffers(1, &m_vbo_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, VERTEX_DATA.size() * sizeof(uint8_t), VERTEX_DATA.data(), GL_STATIC_DRAW));
glsafe(glEnableVertexAttribArray(0));
#ifdef ENABLE_OPENGL_ES
glsafe(glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, (const void*)0));
#else
glsafe(glVertexAttribIPointer(0, 1, GL_UNSIGNED_BYTE, 0, (const void*)0));
#endif // ENABLE_OPENGL_ES
glsafe(glBindBuffer(GL_ARRAY_BUFFER, curr_array_buffer));
glsafe(glBindVertexArray(curr_vertex_array));
}
void SegmentTemplate::shutdown()
{
if (m_vbo_id != 0) {
glsafe(glDeleteBuffers(1, &m_vbo_id));
m_vbo_id = 0;
}
if (m_vao_id != 0) {
glsafe(glDeleteVertexArrays(1, &m_vao_id));
m_vao_id = 0;
}
m_size_in_bytes_gpu = 0;
}
void SegmentTemplate::render(size_t count)
{
if (m_vao_id == 0 || m_vbo_id == 0 || count == 0)
return;
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
glsafe(glBindVertexArray(m_vao_id));
glsafe(glDrawArraysInstanced(GL_TRIANGLES, 0, static_cast<GLsizei>(VERTEX_DATA.size()), static_cast<GLsizei>(count)));
glsafe(glBindVertexArray(curr_vertex_array));
}
} // namespace libvgcode

View File

@ -0,0 +1,51 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_SEGMENTTEMPLATE_HPP
#define VGCODE_SEGMENTTEMPLATE_HPP
#include <cstddef>
namespace libvgcode {
class SegmentTemplate
{
public:
SegmentTemplate() = default;
~SegmentTemplate() { shutdown(); }
SegmentTemplate(const SegmentTemplate& other) = delete;
SegmentTemplate(SegmentTemplate&& other) = delete;
SegmentTemplate& operator = (const SegmentTemplate& other) = delete;
SegmentTemplate& operator = (SegmentTemplate&& other) = delete;
//
// Initialize gpu buffers.
//
void init();
//
// Release gpu buffers.
//
void shutdown();
void render(size_t count);
//
// Return the size of the data sent to gpu, in bytes.
//
size_t size_in_bytes_gpu() const { return m_size_in_bytes_gpu; }
private:
//
// gpu buffers ids.
//
unsigned int m_vao_id{ 0 };
unsigned int m_vbo_id{ 0 };
//
// Size of the data sent to gpu, in bytes.
//
size_t m_size_in_bytes_gpu{ 0 };
};
} // namespace libvgcode
#endif // VGCODE_SEGMENTTEMPLATE_HPP

View File

@ -0,0 +1,9 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "Settings.hpp"
namespace libvgcode {
} // namespace libvgcode

View File

@ -0,0 +1,70 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_SETTINGS_HPP
#define VGCODE_SETTINGS_HPP
#include "../include/Types.hpp"
#include <map>
namespace libvgcode {
struct Settings
{
//
// Visualization parameters
//
EViewType view_type{ EViewType::FeatureType };
ETimeMode time_mode{ ETimeMode::Normal };
bool top_layer_only_view_range{ false };
bool spiral_vase_mode{ false };
//
// Required update flags
//
bool update_view_full_range{ true };
bool update_enabled_entities{ true };
bool update_colors{ true };
//
// Visibility maps
//
std::array<bool, std::size_t(EOptionType::COUNT)> options_visibility{
false, // Travels
false, // Wipes
false, // Retractions
false, // Unretractions
false, // Seams
false, // ToolChanges
false, // ColorChanges
false, // PausePrints
false, // CustomGCodes
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
false, // CenterOfGravity
true // ToolMarker
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
};
std::array<bool, std::size_t(EGCodeExtrusionRole::COUNT)> extrusion_roles_visibility{
true, // None
true, // Perimeter
true, // ExternalPerimeter
true, // OverhangPerimeter
true, // InternalInfill
true, // SolidInfill
true, // TopSolidInfill
true, // Ironing
true, // BridgeInfill
true, // GapFill
true, // Skirt
true, // SupportMaterial
true, // SupportMaterialInterface
true, // WipeTower
true // Custom
};
};
} // namespace libvgcode
#endif // VGCODE_SETTINGS_HPP

View File

@ -0,0 +1,299 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_SHADERS_HPP
#define VGCODE_SHADERS_HPP
// needed for tech VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include "../include/Types.hpp"
namespace libvgcode {
static const char* Segments_Vertex_Shader =
"#version 150\n"
"#define POINTY_CAPS\n"
"#define FIX_TWISTING\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.15;\n"
"const vec3 UP = vec3(0, 0, 1);\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform vec3 camera_position;\n"
"uniform samplerBuffer position_tex;\n"
"uniform samplerBuffer height_width_angle_tex;\n"
"uniform samplerBuffer color_tex;\n"
"uniform usamplerBuffer segment_index_tex;\n"
"in int vertex_id;\n"
"out vec3 color;\n"
"vec3 decode_color(float color) {\n"
" int c = int(round(color));\n"
" int r = (c >> 16) & 0xFF;\n"
" int g = (c >> 8) & 0xFF;\n"
" int b = (c >> 0) & 0xFF;\n"
" float f = 1.0 / 255.0f;\n"
" return f * vec3(r, g, b);\n"
"}\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" int id_a = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n"
" int id_b = id_a + 1;\n"
" vec3 pos_a = texelFetch(position_tex, id_a).xyz;\n"
" vec3 pos_b = texelFetch(position_tex, id_b).xyz;\n"
" vec3 line = pos_b - pos_a;\n"
" // directions of the line box in world space\n"
" float line_len = length(line);\n"
" vec3 line_dir;\n"
" if (line_len < 1e-4)\n"
" line_dir = vec3(1.0, 0.0, 0.0);\n"
" else\n"
" line_dir = line / line_len;\n"
" vec3 line_right_dir;\n"
" if (abs(dot(line_dir, UP)) > 0.9) {\n"
" // For vertical lines, the width and height should be same, there is no concept of up and down.\n"
" // For simplicity, the code will expand width in the x axis, and height in the y axis\n"
" line_right_dir = normalize(cross(vec3(1, 0, 0), line_dir));\n"
" }\n"
" else\n"
" line_right_dir = normalize(cross(line_dir, UP));\n"
" vec3 line_up_dir = normalize(cross(line_right_dir, line_dir));\n"
" const vec2 horizontal_vertical_view_signs_array[16] = vec2[](\n"
" //horizontal view (from right)\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(0.0, 0.0),\n"
" vec2(0.0, -1.0),\n"
" vec2(0.0, -1.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(0.0, 0.0),\n"
" // vertical view (from top)\n"
" vec2(0.0, 1.0),\n"
" vec2(-1.0, 0.0),\n"
" vec2(0.0, 0.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(-1.0, 0.0),\n"
" vec2(0.0, 0.0)\n"
" );\n"
" int id = vertex_id < 4 ? id_a : id_b;\n"
" vec3 endpoint_pos = vertex_id < 4 ? pos_a : pos_b;\n"
" vec3 height_width_angle = texelFetch(height_width_angle_tex, id).xyz;\n"
"#ifdef FIX_TWISTING\n"
" int closer_id = (dot(camera_position - pos_a, camera_position - pos_a) < dot(camera_position - pos_b, camera_position - pos_b)) ? id_a : id_b;\n"
" vec3 closer_pos = (closer_id == id_a) ? pos_a : pos_b;\n"
" vec3 camera_view_dir = normalize(closer_pos - camera_position);\n"
" vec3 closer_height_width_angle = texelFetch(height_width_angle_tex, closer_id).xyz;\n"
" vec3 diagonal_dir_border = normalize(closer_height_width_angle.x * line_up_dir + closer_height_width_angle.y * line_right_dir);\n"
"#else\n"
" vec3 camera_view_dir = normalize(endpoint_pos - camera_position);\n"
" vec3 diagonal_dir_border = normalize(height_width_angle.x * line_up_dir + height_width_angle.y * line_right_dir);\n"
"#endif\n"
" bool is_vertical_view = abs(dot(camera_view_dir, line_up_dir)) / abs(dot(diagonal_dir_border, line_up_dir)) >\n"
" abs(dot(camera_view_dir, line_right_dir)) / abs(dot(diagonal_dir_border, line_right_dir));\n"
" vec2 signs = horizontal_vertical_view_signs_array[vertex_id + 8 * int(is_vertical_view)];\n"
"#ifndef POINTY_CAPS\n"
" if (vertex_id == 2 || vertex_id == 7) signs = -horizontal_vertical_view_signs_array[(vertex_id - 2) + 8 * int(is_vertical_view)];\n"
"#endif\n"
" float view_right_sign = sign(dot(-camera_view_dir, line_right_dir));\n"
" float view_top_sign = sign(dot(-camera_view_dir, line_up_dir));\n"
" float half_height = 0.5 * height_width_angle.x;\n"
" float half_width = 0.5 * height_width_angle.y;\n"
" vec3 horizontal_dir = half_width * line_right_dir;\n"
" vec3 vertical_dir = half_height * line_up_dir;\n"
" float horizontal_sign = signs.x * view_right_sign;\n"
" float vertical_sign = signs.y * view_top_sign;\n"
" vec3 pos = endpoint_pos + horizontal_sign * horizontal_dir + vertical_sign * vertical_dir;\n"
" if (vertex_id == 2 || vertex_id == 7) {\n"
" float line_dir_sign = (vertex_id == 2) ? -1.0 : 1.0;\n"
" if (height_width_angle.z == 0) {\n"
"#ifdef POINTY_CAPS\n"
" // There I add a cap to lines that do not have a following line\n"
" // (or they have one, but perfectly aligned, so the cap is hidden inside the next line).\n"
" pos += line_dir_sign * line_dir * half_width;\n"
"#endif\n"
" }\n"
" else {\n"
" pos += line_dir_sign * line_dir * half_width * sin(abs(height_width_angle.z) * 0.5);\n"
" pos += sign(height_width_angle.z) * horizontal_dir * cos(abs(height_width_angle.z) * 0.5);\n"
" }\n"
" }\n"
" vec3 eye_position = (view_matrix * vec4(pos, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(normalize(pos - endpoint_pos), 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, id).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Segments_Fragment_Shader =
"#version 150\n"
"in vec3 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = vec4(color, 1.0);\n"
"}\n";
static const char* Options_Vertex_Shader =
"#version 150\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"const float scaling_factor = 1.5;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform samplerBuffer position_tex;\n"
"uniform samplerBuffer height_width_angle_tex;\n"
"uniform samplerBuffer color_tex;\n"
"uniform usamplerBuffer segment_index_tex;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out vec3 color;\n"
"vec3 decode_color(float color) {\n"
" int c = int(round(color));\n"
" int r = (c >> 16) & 0xFF;\n"
" int g = (c >> 8) & 0xFF;\n"
" int b = (c >> 0) & 0xFF;\n"
" float f = 1.0 / 255.0f;\n"
" return f * vec3(r, g, b);\n"
"}\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" int id = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n"
" vec2 height_width = texelFetch(height_width_angle_tex, id).xy;\n"
" vec3 offset = texelFetch(position_tex, id).xyz - vec3(0.0, 0.0, 0.5 * height_width.x);\n"
" height_width *= scaling_factor;\n"
" mat3 scale_matrix = mat3(\n"
" height_width.y, 0.0, 0.0,\n"
" 0.0, height_width.y, 0.0,\n"
" 0.0, 0.0, height_width.x);\n"
" vec3 eye_position = (view_matrix * vec4(scale_matrix * in_position + offset, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, id).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Options_Fragment_Shader =
"#version 150\n"
"in vec3 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = vec4(color, 1.0);\n"
"}\n";
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
static const char* Cog_Marker_Vertex_Shader =
"#version 150\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"uniform vec3 world_center_position;\n"
"uniform float scale_factor;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out float intensity;\n"
"out vec3 world_position;\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" world_position = scale_factor * in_position + world_center_position;\n"
" vec3 eye_position = (view_matrix * vec4(world_position, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" intensity = lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Cog_Marker_Fragment_Shader =
"#version 150\n"
"const vec3 BLACK = vec3(0.05);\n"
"const vec3 WHITE = vec3(0.95);\n"
"uniform vec3 world_center_position;\n"
"in float intensity;\n"
"in vec3 world_position;\n"
"out vec4 out_color;\n"
"void main()\n"
"{\n"
" vec3 delta = world_position - world_center_position;\n"
" vec3 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;\n"
" out_color = intensity * vec4(color, 1.0);\n"
"}\n";
static const char* Tool_Marker_Vertex_Shader =
"#version 150\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"uniform vec3 world_origin;\n"
"uniform float scale_factor;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform vec4 color_base;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out vec4 color;\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" vec3 world_position = scale_factor * in_position + world_origin;\n"
" vec3 eye_position = (view_matrix * vec4(world_position, 1.0)).xyz;\n"
" // no need of normal matrix as the scaling is uniform\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" color = vec4(color_base.rgb * lighting(eye_position, eye_normal), color_base.a);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Tool_Marker_Fragment_Shader =
"#version 150\n"
"in vec4 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = color;\n"
"}\n";
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
} // namespace libvgcode
#endif // VGCODE_SHADERS_HPP

View File

@ -0,0 +1,322 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_SHADERSES_HPP
#define VGCODE_SHADERSES_HPP
// needed for tech VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include "../include/Types.hpp"
namespace libvgcode {
static const char* Segments_Vertex_Shader_ES =
"#version 300 es\n"
"precision lowp usampler2D;\n"
"#define POINTY_CAPS\n"
"#define FIX_TWISTING\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.15;\n"
"const vec3 UP = vec3(0, 0, 1);\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform vec3 camera_position;\n"
"uniform sampler2D position_tex;\n"
"uniform sampler2D height_width_angle_tex;\n"
"uniform sampler2D color_tex;\n"
"uniform usampler2D segment_index_tex;\n"
"in float vertex_id_float;\n"
"out vec3 color;\n"
"vec3 decode_color(float color) {\n"
" int c = int(round(color));\n"
" int r = (c >> 16) & 0xFF;\n"
" int g = (c >> 8) & 0xFF;\n"
" int b = (c >> 0) & 0xFF;\n"
" float f = 1.0 / 255.0f;\n"
" return f * vec3(r, g, b);\n"
"}\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"ivec2 tex_coord(sampler2D sampler, int id) {\n"
" ivec2 tex_size = textureSize(sampler, 0);\n"
" return (tex_size.y == 1) ? ivec2(id, 0) : ivec2(id % tex_size.x, id / tex_size.x);\n"
"}\n"
"ivec2 tex_coord_u(usampler2D sampler, int id) {\n"
" ivec2 tex_size = textureSize(sampler, 0);\n"
" return (tex_size.y == 1) ? ivec2(id, 0) : ivec2(id % tex_size.x, id / tex_size.x);\n"
"}\n"
"void main() {\n"
" int vertex_id = int(vertex_id_float);\n"
" int id_a = int(texelFetch(segment_index_tex, tex_coord_u(segment_index_tex, gl_InstanceID), 0).r);\n"
" int id_b = id_a + 1;\n"
" vec3 pos_a = texelFetch(position_tex, tex_coord(position_tex, id_a), 0).xyz;\n"
" vec3 pos_b = texelFetch(position_tex, tex_coord(position_tex, id_b), 0).xyz;\n"
" vec3 line = pos_b - pos_a;\n"
" // directions of the line box in world space\n"
" float line_len = length(line);\n"
" vec3 line_dir;\n"
" if (line_len < 1e-4)\n"
" line_dir = vec3(1.0, 0.0, 0.0);\n"
" else\n"
" line_dir = line / line_len;\n"
" vec3 line_right_dir;\n"
" if (abs(dot(line_dir, UP)) > 0.9) {\n"
" // For vertical lines, the width and height should be same, there is no concept of up and down.\n"
" // For simplicity, the code will expand width in the x axis, and height in the y axis\n"
" line_right_dir = normalize(cross(vec3(1, 0, 0), line_dir));\n"
" }\n"
" else\n"
" line_right_dir = normalize(cross(line_dir, UP));\n"
" vec3 line_up_dir = normalize(cross(line_right_dir, line_dir));\n"
" const vec2 horizontal_vertical_view_signs_array[16] = vec2[](\n"
" //horizontal view (from right)\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(0.0, 0.0),\n"
" vec2(0.0, -1.0),\n"
" vec2(0.0, -1.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(0.0, 0.0),\n"
" // vertical view (from top)\n"
" vec2(0.0, 1.0),\n"
" vec2(-1.0, 0.0),\n"
" vec2(0.0, 0.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(1.0, 0.0),\n"
" vec2(0.0, 1.0),\n"
" vec2(-1.0, 0.0),\n"
" vec2(0.0, 0.0)\n"
" );\n"
" int id = vertex_id < 4 ? id_a : id_b;\n"
" vec3 endpoint_pos = vertex_id < 4 ? pos_a : pos_b;\n"
" vec3 height_width_angle = texelFetch(height_width_angle_tex, tex_coord(height_width_angle_tex, id), 0).xyz;\n"
"#ifdef FIX_TWISTING\n"
" int closer_id = (dot(camera_position - pos_a, camera_position - pos_a) < dot(camera_position - pos_b, camera_position - pos_b)) ? id_a : id_b;\n"
" vec3 closer_pos = (closer_id == id_a) ? pos_a : pos_b;\n"
" vec3 camera_view_dir = normalize(closer_pos - camera_position);\n"
" vec3 closer_height_width_angle = texelFetch(height_width_angle_tex, tex_coord(height_width_angle_tex, closer_id), 0).xyz;\n"
" vec3 diagonal_dir_border = normalize(closer_height_width_angle.x * line_up_dir + closer_height_width_angle.y * line_right_dir);\n"
"#else\n"
" vec3 camera_view_dir = normalize(endpoint_pos - camera_position);\n"
" vec3 diagonal_dir_border = normalize(height_width_angle.x * line_up_dir + height_width_angle.y * line_right_dir);\n"
"#endif\n"
" bool is_vertical_view = abs(dot(camera_view_dir, line_up_dir)) / abs(dot(diagonal_dir_border, line_up_dir)) >\n"
" abs(dot(camera_view_dir, line_right_dir)) / abs(dot(diagonal_dir_border, line_right_dir));\n"
" vec2 signs = horizontal_vertical_view_signs_array[vertex_id + 8 * int(is_vertical_view)];\n"
"#ifndef POINTY_CAPS\n"
" if (vertex_id == 2 || vertex_id == 7) signs = -horizontal_vertical_view_signs_array[(vertex_id - 2) + 8 * int(is_vertical_view)];\n"
"#endif\n"
" float view_right_sign = sign(dot(-camera_view_dir, line_right_dir));\n"
" float view_top_sign = sign(dot(-camera_view_dir, line_up_dir));\n"
" float half_height = 0.5 * height_width_angle.x;\n"
" float half_width = 0.5 * height_width_angle.y;\n"
" vec3 horizontal_dir = half_width * line_right_dir;\n"
" vec3 vertical_dir = half_height * line_up_dir;\n"
" float horizontal_sign = signs.x * view_right_sign;\n"
" float vertical_sign = signs.y * view_top_sign;\n"
" vec3 pos = endpoint_pos + horizontal_sign * horizontal_dir + vertical_sign * vertical_dir;\n"
" if (vertex_id == 2 || vertex_id == 7) {\n"
" float line_dir_sign = (vertex_id == 2) ? -1.0 : 1.0;\n"
" if (height_width_angle.z == 0.0) {\n"
"#ifdef POINTY_CAPS\n"
" // There I add a cap to lines that do not have a following line\n"
" // (or they have one, but perfectly aligned, so the cap is hidden inside the next line).\n"
" pos += line_dir_sign * line_dir * half_width;\n"
"#endif\n"
" }\n"
" else {\n"
" pos += line_dir_sign * line_dir * half_width * sin(abs(height_width_angle.z) * 0.5);\n"
" pos += sign(height_width_angle.z) * horizontal_dir * cos(abs(height_width_angle.z) * 0.5);\n"
" }\n"
" }\n"
" vec3 eye_position = (view_matrix * vec4(pos, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(normalize(pos - endpoint_pos), 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, tex_coord(color_tex, id), 0).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Segments_Fragment_Shader_ES =
"#version 300 es\n"
"precision highp float;\n"
"in vec3 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = vec4(color, 1.0);\n"
"}\n";
static const char* Options_Vertex_Shader_ES =
"#version 300 es\n"
"precision lowp usampler2D;\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"const float scaling_factor = 1.5;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform sampler2D position_tex;\n"
"uniform sampler2D height_width_angle_tex;\n"
"uniform sampler2D color_tex;\n"
"uniform usampler2D segment_index_tex;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out vec3 color;\n"
"vec3 decode_color(float color) {\n"
" int c = int(round(color));\n"
" int r = (c >> 16) & 0xFF;\n"
" int g = (c >> 8) & 0xFF;\n"
" int b = (c >> 0) & 0xFF;\n"
" float f = 1.0 / 255.0f;\n"
" return f * vec3(r, g, b);\n"
"}\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"ivec2 tex_coord(sampler2D sampler, int id) {\n"
" ivec2 tex_size = textureSize(sampler, 0);\n"
" return (tex_size.y == 1) ? ivec2(id, 0) : ivec2(id % tex_size.x, id / tex_size.x);\n"
"}\n"
"ivec2 tex_coord_u(usampler2D sampler, int id) {\n"
" ivec2 tex_size = textureSize(sampler, 0);\n"
" return (tex_size.y == 1) ? ivec2(id, 0) : ivec2(id % tex_size.x, id / tex_size.x);\n"
"}\n"
"void main() {\n"
" int id = int(texelFetch(segment_index_tex, tex_coord_u(segment_index_tex, gl_InstanceID), 0).r);\n"
" vec2 height_width = texelFetch(height_width_angle_tex, tex_coord(height_width_angle_tex, id), 0).xy;\n"
" vec3 offset = texelFetch(position_tex, tex_coord(position_tex, id), 0).xyz - vec3(0.0, 0.0, 0.5 * height_width.x);\n"
" height_width *= scaling_factor;\n"
" mat3 scale_matrix = mat3(\n"
" height_width.y, 0.0, 0.0,\n"
" 0.0, height_width.y, 0.0,\n"
" 0.0, 0.0, height_width.x);\n"
" vec3 eye_position = (view_matrix * vec4(scale_matrix * in_position + offset, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, tex_coord(color_tex, id), 0).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Options_Fragment_Shader_ES =
"#version 300 es\n"
"precision highp float;\n"
"in vec3 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = vec4(color, 1.0);\n"
"}\n";
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
static const char* Cog_Marker_Vertex_Shader_ES =
"#version 300 es\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"uniform vec3 world_center_position;\n"
"uniform float scale_factor;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out float intensity;\n"
"out vec3 world_position;\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" world_position = scale_factor * in_position + world_center_position;\n"
" vec3 eye_position = (view_matrix * vec4(world_position, 1.0)).xyz;\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" intensity = lighting(eye_position, eye_normal);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Cog_Marker_Fragment_Shader_ES =
"#version 300 es\n"
"precision highp float;\n"
"const vec3 BLACK = vec3(0.05);\n"
"const vec3 WHITE = vec3(0.95);\n"
"uniform vec3 world_center_position;\n"
"in float intensity;\n"
"in vec3 world_position;\n"
"out vec4 out_color;\n"
"void main()\n"
"{\n"
" vec3 delta = world_position - world_center_position;\n"
" vec3 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;\n"
" out_color = intensity * vec4(color, 1.0);\n"
"}\n";
static const char* Tool_Marker_Vertex_Shader_ES =
"#version 300 es\n"
"const vec3 light_top_dir = vec3(-0.4574957, 0.4574957, 0.7624929);\n"
"const float light_top_diffuse = 0.6 * 0.8;\n"
"const float light_top_specular = 0.6 * 0.125;\n"
"const float light_top_shininess = 20.0;\n"
"const vec3 light_front_dir = vec3(0.6985074, 0.1397015, 0.6985074);\n"
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
"uniform vec3 world_origin;\n"
"uniform float scale_factor;\n"
"uniform mat4 view_matrix;\n"
"uniform mat4 projection_matrix;\n"
"uniform vec4 color_base;\n"
"in vec3 in_position;\n"
"in vec3 in_normal;\n"
"out vec4 color;\n"
"float lighting(vec3 eye_position, vec3 eye_normal) {\n"
" float top_diffuse = light_top_diffuse * max(dot(eye_normal, light_top_dir), 0.0);\n"
" float front_diffuse = light_front_diffuse * max(dot(eye_normal, light_front_dir), 0.0);\n"
" float top_specular = light_top_specular * pow(max(dot(-normalize(eye_position), reflect(-light_top_dir, eye_normal)), 0.0), light_top_shininess);\n"
" return ambient + top_diffuse + front_diffuse + top_specular + emission;\n"
"}\n"
"void main() {\n"
" vec3 world_position = scale_factor * in_position + world_origin;\n"
" vec3 eye_position = (view_matrix * vec4(world_position, 1.0)).xyz;\n"
" // no need of normal matrix as the scaling is uniform\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" color = vec4(color_base.rgb * lighting(eye_position, eye_normal), color_base.a);\n"
" gl_Position = projection_matrix * vec4(eye_position, 1.0);\n"
"}\n";
static const char* Tool_Marker_Fragment_Shader_ES =
"#version 300 es\n"
"precision highp float;\n"
"in vec4 color;\n"
"out vec4 fragment_color;\n"
"void main() {\n"
" fragment_color = color;\n"
"}\n";
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
} // namespace libvgcode
#endif // VGCODE_SHADERSES_HPP

View File

@ -0,0 +1,172 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "ToolMarker.hpp"
#include "OpenGLUtils.hpp"
#include "Utils.hpp"
#include <cmath>
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
namespace libvgcode {
// Geometry:
// Arrow with cylindrical stem and conical tip, with the given dimensions and resolution
// The origin of the arrow is at the tip of the conical section
// The axis of symmetry is along the Z axis
// The arrow is pointing downward
void ToolMarker::init(uint16_t resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
{
if (m_vao_id != 0)
return;
// ensure vertices count does not exceed 65536
resolution = std::clamp<uint16_t>(resolution, 4, 10922);
std::vector<float> vertices;
const uint16_t vertices_count = 6 * resolution + 2;
vertices.reserve(6 * vertices_count);
m_indices_count = 6 * resolution * 3;
std::vector<uint16_t> indices;
indices.reserve(m_indices_count);
const float angle_step = 2.0f * PI / float(resolution);
std::vector<float> cosines(resolution);
std::vector<float> sines(resolution);
for (uint16_t i = 0; i < resolution; ++i) {
const float angle = angle_step * float(i);
cosines[i] = std::cos(angle);
sines[i] = -std::sin(angle);
}
const float total_height = tip_height + stem_height;
// tip vertices
add_vertex({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }, vertices);
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ tip_radius * sines[i], tip_radius * cosines[i], tip_height }, { sines[i], cosines[i], 0.0f }, vertices);
}
// tip triangles
for (uint16_t i = 0; i < resolution; ++i) {
const uint16_t v3 = (i < resolution - 1) ? i + 2 : 1;
add_triangle(0, i + 1, v3, indices);
}
// tip cap outer perimeter vertices
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ tip_radius * sines[i], tip_radius * cosines[i], tip_height }, { 0.0f, 0.0f, 1.0f }, vertices);
}
// tip cap inner perimeter vertices
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ stem_radius * sines[i], stem_radius * cosines[i], tip_height }, { 0.0f, 0.0f, 1.0f }, vertices);
}
// tip cap triangles
for (uint16_t i = 0; i < resolution; ++i) {
const uint16_t v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
const uint16_t v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
add_triangle(i + resolution + 1, v3, v2, indices);
add_triangle(i + resolution + 1, i + 2 * resolution + 1, v3, indices);
}
// stem bottom vertices
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ stem_radius * sines[i], stem_radius * cosines[i], tip_height }, { sines[i], cosines[i], 0.0f }, vertices);
}
// stem top vertices
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ stem_radius * sines[i], stem_radius * cosines[i], total_height }, { sines[i], cosines[i], 0.0f }, vertices);
}
// stem triangles
for (uint16_t i = 0; i < resolution; ++i) {
const uint16_t v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
const uint16_t v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
add_triangle(i + 3 * resolution + 1, v3, v2, indices);
add_triangle(i + 3 * resolution + 1, i + 4 * resolution + 1, v3, indices);
}
// stem cap vertices
add_vertex({ 0.0f, 0.0f, total_height }, { 0.0f, 0.0f, 1.0f }, vertices);
for (uint16_t i = 0; i < resolution; ++i) {
add_vertex({ stem_radius * sines[i], stem_radius * cosines[i], total_height }, { 0.0f, 0.0f, 1.0f }, vertices);
}
// stem cap triangles
for (uint16_t i = 0; i < resolution; ++i) {
const uint16_t v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
add_triangle(5 * resolution + 1, v3, i + 5 * resolution + 2, indices);
}
m_size_in_bytes_gpu += vertices.size() * sizeof(float);
m_size_in_bytes_gpu += indices.size() * sizeof(uint16_t);
const size_t vertex_stride = 6 * sizeof(float);
const size_t position_offset = 0;
const size_t normal_offset = 3 * sizeof(float);
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
int curr_array_buffer;
glsafe(glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &curr_array_buffer));
glsafe(glGenVertexArrays(1, &m_vao_id));
glsafe(glBindVertexArray(m_vao_id));
glsafe(glGenBuffers(1, &m_vbo_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
glsafe(glEnableVertexAttribArray(0));
glsafe(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)position_offset));
glsafe(glEnableVertexAttribArray(1));
glsafe(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_stride, (const void*)normal_offset));
glsafe(glGenBuffers(1, &m_ibo_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.data(), GL_STATIC_DRAW));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, curr_array_buffer));
glsafe(glBindVertexArray(curr_vertex_array));
}
void ToolMarker::shutdown()
{
if (m_ibo_id != 0) {
glsafe(glDeleteBuffers(1, &m_ibo_id));
m_ibo_id = 0;
}
if (m_vbo_id != 0) {
glsafe(glDeleteBuffers(1, &m_vbo_id));
m_vbo_id = 0;
}
if (m_vao_id != 0) {
glsafe(glDeleteVertexArrays(1, &m_vao_id));
m_vao_id = 0;
}
m_size_in_bytes_gpu = 0;
}
void ToolMarker::render()
{
if (m_vao_id == 0 || m_vbo_id == 0 || m_ibo_id == 0)
return;
int curr_vertex_array;
glsafe(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &curr_vertex_array));
glcheck();
glsafe(glBindVertexArray(m_vao_id));
glsafe(glDrawElements(GL_TRIANGLES, m_indices_count, GL_UNSIGNED_SHORT, (const void*)0));
glsafe(glBindVertexArray(curr_vertex_array));
}
} // namespace libvgcode
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS

View File

@ -0,0 +1,75 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_TOOLMARKER_HPP
#define VGCODE_TOOLMARKER_HPP
#include "../include/Types.hpp"
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include <algorithm>
namespace libvgcode {
class ToolMarker
{
public:
ToolMarker() = default;
~ToolMarker() { shutdown(); }
ToolMarker(const ToolMarker& other) = delete;
ToolMarker(ToolMarker&& other) = delete;
ToolMarker& operator = (const ToolMarker& other) = delete;
ToolMarker& operator = (ToolMarker&& other) = delete;
//
// Initialize gpu buffers.
//
void init(uint16_t resolution, float tip_radius, float tip_height, float stem_radius, float stem_height);
//
// Release gpu buffers.
//
void shutdown();
void render();
const Vec3& get_position() const { return m_position; }
void set_position(const Vec3& position) { m_position = position; }
float get_offset_z() const { return m_offset_z; }
void set_offset_z(float offset_z) { m_offset_z = std::max(offset_z, 0.0f); }
const Color& get_color() const { return m_color; }
void set_color(const Color& color) { m_color = color; }
float get_alpha() const { return m_alpha; }
void set_alpha(float alpha) { m_alpha = std::clamp(alpha, 0.25f, 0.75f); }
//
// Return the size of the data sent to gpu, in bytes.
//
size_t size_in_bytes_gpu() const { return m_size_in_bytes_gpu; }
private:
Vec3 m_position{ 0.0f, 0.0f, 0.0f };
float m_offset_z{ 0.5f };
Color m_color{ 255, 255, 255 };
float m_alpha{ 0.5f };
uint16_t m_indices_count{ 0 };
//
// gpu buffers ids.
//
unsigned int m_vao_id{ 0 };
unsigned int m_vbo_id{ 0 };
unsigned int m_ibo_id{ 0 };
//
// Size of the data sent to gpu, in bytes.
//
size_t m_size_in_bytes_gpu{ 0 };
};
} // namespace libvgcode
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // VGCODE_TOOLMARKER_HPP

View File

@ -0,0 +1,42 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/Types.hpp"
#include <algorithm>
namespace libvgcode {
// mapping from EMoveType to EOptionType
EOptionType move_type_to_option(EMoveType type)
{
switch (type)
{
case EMoveType::Travel: { return EOptionType::Travels; }
case EMoveType::Wipe: { return EOptionType::Wipes; }
case EMoveType::Retract: { return EOptionType::Retractions; }
case EMoveType::Unretract: { return EOptionType::Unretractions; }
case EMoveType::Seam: { return EOptionType::Seams; }
case EMoveType::ToolChange: { return EOptionType::ToolChanges; }
case EMoveType::ColorChange: { return EOptionType::ColorChanges; }
case EMoveType::PausePrint: { return EOptionType::PausePrints; }
case EMoveType::CustomGCode: { return EOptionType::CustomGCodes; }
default: { return EOptionType::COUNT; }
}
}
static uint8_t lerp(uint8_t f1, uint8_t f2, float t)
{
const float one_minus_t = 1.0f - t;
return static_cast<uint8_t>(one_minus_t * static_cast<float>(f1) + t * static_cast<float>(f2));
}
// It will be possible to replace this with std::lerp when using c++20
Color lerp(const Color& c1, const Color& c2, float t)
{
t = std::clamp(t, 0.0f, 1.0f);
return { lerp(c1[0], c2[0], t), lerp(c1[1], c2[1], t), lerp(c1[2], c2[2], t) };
}
} // namespace libvgcode

View File

@ -0,0 +1,68 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "Utils.hpp"
#include <assert.h>
#include <cmath>
namespace libvgcode {
void add_vertex(const Vec3& position, const Vec3& normal, std::vector<float>& vertices)
{
vertices.emplace_back(position[0]);
vertices.emplace_back(position[1]);
vertices.emplace_back(position[2]);
vertices.emplace_back(normal[0]);
vertices.emplace_back(normal[1]);
vertices.emplace_back(normal[2]);
}
void add_triangle(uint16_t v1, uint16_t v2, uint16_t v3, std::vector<uint16_t>& indices)
{
indices.emplace_back(v1);
indices.emplace_back(v2);
indices.emplace_back(v3);
}
Vec3 normalize(const Vec3& v)
{
const float length = std::sqrt(dot(v, v));
assert(length > 0.0f);
const float inv_length = 1.0f / length;
return { v[0] * inv_length, v[1] * inv_length, v[2] * inv_length };
}
float dot(const Vec3& v1, const Vec3& v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
float length(const Vec3& v)
{
return std::sqrt(dot(v, v));
}
bool operator == (const Vec3& v1, const Vec3& v2) {
return v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2];
}
bool operator != (const Vec3& v1, const Vec3& v2) {
return v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2];
}
Vec3 operator + (const Vec3& v1, const Vec3& v2) {
return { v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2] };
}
Vec3 operator - (const Vec3& v1, const Vec3& v2) {
return { v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2] };
}
Vec3 operator * (float f, const Vec3& v) {
return { f * v[0], f * v[1], f * v[2] };
}
} // namespace libvgcode

View File

@ -0,0 +1,31 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_UTILS_HPP
#define VGCODE_UTILS_HPP
#include "../include/Types.hpp"
#ifdef _WIN32
#define STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
#else
#define STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
#endif // _WIN32
namespace libvgcode {
extern void add_vertex(const Vec3& position, const Vec3& normal, std::vector<float>& vertices);
extern void add_triangle(uint16_t v1, uint16_t v2, uint16_t v3, std::vector<uint16_t>& indices);
extern Vec3 normalize(const Vec3& v);
extern float dot(const Vec3& v1, const Vec3& v2);
extern float length(const Vec3& v);
extern bool operator == (const Vec3& v1, const Vec3& v2);
extern bool operator != (const Vec3& v1, const Vec3& v2);
extern Vec3 operator + (const Vec3& v1, const Vec3& v2);
extern Vec3 operator - (const Vec3& v1, const Vec3& v2);
extern Vec3 operator * (float f, const Vec3& v);
} // namespace libvgcode
#endif // VGCODE_UTILS_HPP

View File

@ -0,0 +1,39 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "ViewRange.hpp"
namespace libvgcode {
void ViewRange::set_full(Interval::value_type min, Interval::value_type max)
{
m_full.set(min, max);
// force the enabled range to stay inside the modified full range
m_full.clamp(m_enabled);
// force the visible range to stay inside the modified enabled range
m_enabled.clamp(m_visible);
}
void ViewRange::set_enabled(Interval::value_type min, Interval::value_type max)
{
m_enabled.set(min, max);
// force the visible range to stay inside the modified enabled range
m_enabled.clamp(m_visible);
}
void ViewRange::set_visible(Interval::value_type min, Interval::value_type max)
{
m_visible.set(min, max);
// force the visible range to stay inside the enabled range
m_enabled.clamp(m_visible);
}
void ViewRange::reset()
{
m_full.reset();
m_enabled.reset();
m_visible.reset();
}
} // namespace libvgcode

View File

@ -0,0 +1,56 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_VIEWRANGE_HPP
#define VGCODE_VIEWRANGE_HPP
#include "Range.hpp"
namespace libvgcode {
class ViewRange
{
public:
const Interval& get_full() const { return m_full.get(); }
void set_full(const Range& other) { set_full(other.get()); }
void set_full(const Interval& range) { set_full(range[0], range[1]); }
void set_full(Interval::value_type min, Interval::value_type max);
const Interval& get_enabled() const { return m_enabled.get(); }
void set_enabled(const Range& other) { set_enabled(other.get()); }
void set_enabled(const Interval& range) { set_enabled(range[0], range[1]); }
void set_enabled(Interval::value_type min, Interval::value_type max);
const Interval& get_visible() const { return m_visible.get(); }
void set_visible(const Range& other) { set_visible(other.get()); }
void set_visible(const Interval& range) { set_visible(range[0], range[1]); }
void set_visible(Interval::value_type min, Interval::value_type max);
void reset();
private:
//
// Full range
// The range of moves that could potentially be visible.
// It is usually equal to the enabled range, unless Settings::top_layer_only_view_range is set to true.
//
Range m_full;
//
// Enabled range
// The range of moves that are enabled for visualization.
// It is usually equal to the full range, unless Settings::top_layer_only_view_range is set to true.
//
Range m_enabled;
//
// Visible range
// The range of moves that are currently rendered.
//
Range m_visible;
};
} // namespace libvgcode
#endif // VGCODE_VIEWRANGE_HPP

View File

@ -0,0 +1,422 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#include "../include/Viewer.hpp"
#include "ViewerImpl.hpp"
namespace libvgcode {
Viewer::Viewer()
{
m_impl = new ViewerImpl();
}
Viewer::~Viewer()
{
delete m_impl;
}
void Viewer::init(const std::string& opengl_context_version)
{
m_impl->init(opengl_context_version);
}
void Viewer::shutdown()
{
m_impl->shutdown();
}
void Viewer::reset()
{
m_impl->reset();
}
void Viewer::load(GCodeInputData&& gcode_data)
{
m_impl->load(std::move(gcode_data));
}
void Viewer::render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix)
{
m_impl->render(view_matrix, projection_matrix);
}
EViewType Viewer::get_view_type() const
{
return m_impl->get_view_type();
}
void Viewer::set_view_type(EViewType type)
{
m_impl->set_view_type(type);
}
ETimeMode Viewer::get_time_mode() const
{
return m_impl->get_time_mode();
}
void Viewer::set_time_mode(ETimeMode mode)
{
m_impl->set_time_mode(mode);
}
bool Viewer::is_top_layer_only_view_range() const
{
return m_impl->is_top_layer_only_view_range();
}
void Viewer::toggle_top_layer_only_view_range()
{
m_impl->toggle_top_layer_only_view_range();
}
bool Viewer::is_option_visible(EOptionType type) const
{
return m_impl->is_option_visible(type);
}
void Viewer::toggle_option_visibility(EOptionType type)
{
m_impl->toggle_option_visibility(type);
}
bool Viewer::is_extrusion_role_visible(EGCodeExtrusionRole role) const
{
return m_impl->is_extrusion_role_visible(role);
}
void Viewer::toggle_extrusion_role_visibility(EGCodeExtrusionRole role)
{
m_impl->toggle_extrusion_role_visibility(role);
}
const Color& Viewer::get_extrusion_role_color(EGCodeExtrusionRole role) const
{
return m_impl->get_extrusion_role_color(role);
}
void Viewer::set_extrusion_role_color(EGCodeExtrusionRole role, const Color& color)
{
m_impl->set_extrusion_role_color(role, color);
}
void Viewer::reset_default_extrusion_roles_colors()
{
m_impl->reset_default_extrusion_roles_colors();
}
const Color& Viewer::get_option_color(EOptionType type) const
{
return m_impl->get_option_color(type);
}
void Viewer::set_option_color(EOptionType type, const Color& color)
{
m_impl->set_option_color(type, color);
}
void Viewer::reset_default_options_colors()
{
m_impl->reset_default_options_colors();
}
size_t Viewer::get_tool_colors_count() const
{
return m_impl->get_tool_colors_count();
}
const Palette& Viewer::get_tool_colors() const
{
return m_impl->get_tool_colors();
}
void Viewer::set_tool_colors(const Palette& colors)
{
m_impl->set_tool_colors(colors);
}
size_t Viewer::get_color_print_colors_count() const
{
return m_impl->get_color_print_colors_count();
}
const Palette& Viewer::get_color_print_colors() const
{
return m_impl->get_color_print_colors();
}
void Viewer::set_color_print_colors(const Palette& colors)
{
m_impl->set_color_print_colors(colors);
}
const ColorRange& Viewer::get_color_range(EViewType type) const
{
return m_impl->get_color_range(type);
}
void Viewer::set_color_range_palette(EViewType type, const Palette& palette)
{
m_impl->set_color_range_palette(type, palette);
}
float Viewer::get_travels_radius() const
{
return m_impl->get_travels_radius();
}
void Viewer::set_travels_radius(float radius)
{
m_impl->set_travels_radius(radius);
}
float Viewer::get_wipes_radius() const
{
return m_impl->get_wipes_radius();
}
void Viewer::set_wipes_radius(float radius)
{
m_impl->set_wipes_radius(radius);
}
size_t Viewer::get_layers_count() const
{
return m_impl->get_layers_count();
}
const Interval& Viewer::get_layers_view_range() const
{
return m_impl->get_layers_view_range();
}
void Viewer::set_layers_view_range(const Interval& range)
{
m_impl->set_layers_view_range(range);
}
void Viewer::set_layers_view_range(Interval::value_type min, Interval::value_type max)
{
m_impl->set_layers_view_range(min, max);
}
const Interval& Viewer::get_view_visible_range() const
{
return m_impl->get_view_visible_range();
}
void Viewer::set_view_visible_range(Interval::value_type min, Interval::value_type max)
{
m_impl->set_view_visible_range(min, max);
}
const Interval& Viewer::get_view_full_range() const
{
return m_impl->get_view_full_range();
}
const Interval& Viewer::get_view_enabled_range() const
{
return m_impl->get_view_enabled_range();
}
bool Viewer::is_spiral_vase_mode() const
{
return m_impl->is_spiral_vase_mode();
}
float Viewer::get_layer_z(size_t layer_id) const
{
return m_impl->get_layer_z(layer_id);
}
std::vector<float> Viewer::get_layers_zs() const
{
return m_impl->get_layers_zs();
}
size_t Viewer::get_layer_id_at(float z) const
{
return m_impl->get_layer_id_at(z);
}
size_t Viewer::get_used_extruders_count() const
{
return m_impl->get_used_extruders_count();
}
std::vector<uint8_t> Viewer::get_used_extruders_ids() const
{
return m_impl->get_used_extruders_ids();
}
std::vector<ETimeMode> Viewer::get_time_modes() const
{
return m_impl->get_time_modes();
}
size_t Viewer::get_vertices_count() const
{
return m_impl->get_vertices_count();
}
const PathVertex& Viewer::get_current_vertex() const
{
return m_impl->get_current_vertex();
}
size_t Viewer::get_current_vertex_id() const
{
return m_impl->get_current_vertex_id();
}
const PathVertex& Viewer::get_vertex_at(size_t id) const
{
return m_impl->get_vertex_at(id);
}
float Viewer::get_estimated_time() const
{
return m_impl->get_estimated_time();
}
float Viewer::get_estimated_time_at(size_t id) const
{
return m_impl->get_estimated_time_at(id);
}
Color Viewer::get_vertex_color(const PathVertex& vertex) const
{
return m_impl->get_vertex_color(vertex);
}
size_t Viewer::get_extrusion_roles_count() const
{
return m_impl->get_extrusion_roles_count();
}
std::vector<EGCodeExtrusionRole> Viewer::get_extrusion_roles() const
{
return m_impl->get_extrusion_roles();
}
size_t Viewer::get_options_count() const
{
return m_impl->get_options_count();
}
const std::vector<EOptionType>& Viewer::get_options() const
{
return m_impl->get_options();
}
size_t Viewer::get_color_prints_count(uint8_t extruder_id) const
{
return m_impl->get_color_prints_count(extruder_id);
}
std::vector<ColorPrint> Viewer::get_color_prints(uint8_t extruder_id) const
{
return m_impl->get_color_prints(extruder_id);
}
float Viewer::get_extrusion_role_estimated_time(EGCodeExtrusionRole role) const
{
return m_impl->get_extrusion_role_estimated_time(role);
}
float Viewer::get_travels_estimated_time() const
{
return m_impl->get_travels_estimated_time();
}
std::vector<float> Viewer::get_layers_estimated_times() const
{
return m_impl->get_layers_estimated_times();
}
AABox Viewer::get_bounding_box(const std::vector<EMoveType>& types) const
{
return m_impl->get_bounding_box(types);
}
AABox Viewer::get_extrusion_bounding_box(const std::vector<EGCodeExtrusionRole>& roles) const
{
return m_impl->get_extrusion_bounding_box(roles);
}
size_t Viewer::get_used_cpu_memory() const
{
return m_impl->get_used_cpu_memory();
}
size_t Viewer::get_used_gpu_memory() const
{
return m_impl->get_used_gpu_memory();
}
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
Vec3 Viewer::get_cog_position() const
{
return m_impl->get_cog_marker_position();
}
float Viewer::get_cog_marker_scale_factor() const
{
return m_impl->get_cog_marker_scale_factor();
}
void Viewer::set_cog_marker_scale_factor(float factor)
{
m_impl->set_cog_marker_scale_factor(factor);
}
const Vec3& Viewer::get_tool_marker_position() const
{
return m_impl->get_tool_marker_position();
}
float Viewer::get_tool_marker_offset_z() const
{
return m_impl->get_tool_marker_offset_z();
}
void Viewer::set_tool_marker_offset_z(float offset_z)
{
m_impl->set_tool_marker_offset_z(offset_z);
}
float Viewer::get_tool_marker_scale_factor() const
{
return m_impl->get_tool_marker_scale_factor();
}
void Viewer::set_tool_marker_scale_factor(float factor)
{
m_impl->set_tool_marker_scale_factor(factor);
}
const Color& Viewer::get_tool_marker_color() const
{
return m_impl->get_tool_marker_color();
}
void Viewer::set_tool_marker_color(const Color& color)
{
m_impl->set_tool_marker_color(color);
}
float Viewer::get_tool_marker_alpha() const
{
return m_impl->get_tool_marker_alpha();
}
void Viewer::set_tool_marker_alpha(float alpha)
{
m_impl->set_tool_marker_alpha(alpha);
}
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
} // namespace libvgcode

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,466 @@
///|/ Copyright (c) Prusa Research 2023 Enrico Turri @enricoturri1966, Pavel Mikuš @Godrak
///|/
///|/ libvgcode is released under the terms of the AGPLv3 or higher
///|/
#ifndef VGCODE_VIEWERIMPL_HPP
#define VGCODE_VIEWERIMPL_HPP
#include "Settings.hpp"
#include "SegmentTemplate.hpp"
#include "OptionTemplate.hpp"
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include "CogMarker.hpp"
#include "ToolMarker.hpp"
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#include "../include/PathVertex.hpp"
#include "../include/ColorRange.hpp"
#include "../include/ColorPrint.hpp"
#include "Bitset.hpp"
#include "ViewRange.hpp"
#include "Layers.hpp"
#include "ExtrusionRoles.hpp"
#include <string>
#include <optional>
namespace libvgcode {
struct GCodeInputData;
class ViewerImpl
{
public:
ViewerImpl();
~ViewerImpl() { shutdown(); }
ViewerImpl(const ViewerImpl& other) = delete;
ViewerImpl(ViewerImpl&& other) = delete;
ViewerImpl& operator = (const ViewerImpl& other) = delete;
ViewerImpl& operator = (ViewerImpl&& other) = delete;
//
// Initialize shaders, uniform indices and segment geometry.
//
void init(const std::string& opengl_context_version);
//
// Release the resources used by the viewer.
//
void shutdown();
//
// Reset all caches and free gpu memory.
//
void reset();
//
// Setup all the variables used for visualization of the toolpaths
// from the given gcode data.
//
void load(GCodeInputData&& gcode_data);
//
// Update the visibility property of toolpaths in dependence
// of the current settings
//
void update_enabled_entities();
//
// Update the color of toolpaths in dependence of the current
// view type and settings
//
void update_colors();
void update_colors_texture();
//
// Render the toolpaths
//
void render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
EViewType get_view_type() const { return m_settings.view_type; }
void set_view_type(EViewType type);
ETimeMode get_time_mode() const { return m_settings.time_mode; }
void set_time_mode(ETimeMode mode);
const Interval& get_layers_view_range() const { return m_layers.get_view_range(); }
void set_layers_view_range(const Interval& range) { set_layers_view_range(range[0], range[1]); }
void set_layers_view_range(Interval::value_type min, Interval::value_type max);
bool is_top_layer_only_view_range() const { return m_settings.top_layer_only_view_range; }
void toggle_top_layer_only_view_range();
bool is_spiral_vase_mode() const { return m_settings.spiral_vase_mode; }
std::vector<ETimeMode> get_time_modes() const;
size_t get_layers_count() const { return m_layers.count(); }
float get_layer_z(size_t layer_id) const { return m_layers.get_layer_z(layer_id); }
std::vector<float> get_layers_zs() const { return m_layers.get_zs(); }
size_t get_layer_id_at(float z) const { return m_layers.get_layer_id_at(z); }
size_t get_used_extruders_count() const { return m_used_extruders.size(); }
std::vector<uint8_t> get_used_extruders_ids() const;
size_t get_color_prints_count(uint8_t extruder_id) const;
std::vector<ColorPrint> get_color_prints(uint8_t extruder_id) const;
AABox get_bounding_box(const std::vector<EMoveType>& types = {
EMoveType::Retract, EMoveType::Unretract, EMoveType::Seam, EMoveType::ToolChange,
EMoveType::ColorChange, EMoveType::PausePrint, EMoveType::CustomGCode, EMoveType::Travel,
EMoveType::Wipe, EMoveType::Extrude }) const;
AABox get_extrusion_bounding_box(const std::vector<EGCodeExtrusionRole>& roles = {
EGCodeExtrusionRole::Perimeter, EGCodeExtrusionRole::ExternalPerimeter, EGCodeExtrusionRole::OverhangPerimeter,
EGCodeExtrusionRole::InternalInfill, EGCodeExtrusionRole::SolidInfill, EGCodeExtrusionRole::TopSolidInfill,
EGCodeExtrusionRole::Ironing, EGCodeExtrusionRole::BridgeInfill, EGCodeExtrusionRole::GapFill,
EGCodeExtrusionRole::Skirt, EGCodeExtrusionRole::SupportMaterial, EGCodeExtrusionRole::SupportMaterialInterface,
EGCodeExtrusionRole::WipeTower, EGCodeExtrusionRole::Custom }) const;
bool is_option_visible(EOptionType type) const;
void toggle_option_visibility(EOptionType type);
bool is_extrusion_role_visible(EGCodeExtrusionRole role) const;
void toggle_extrusion_role_visibility(EGCodeExtrusionRole role);
const Interval& get_view_full_range() const { return m_view_range.get_full(); }
const Interval& get_view_enabled_range() const { return m_view_range.get_enabled(); }
const Interval& get_view_visible_range() const { return m_view_range.get_visible(); }
void set_view_visible_range(Interval::value_type min, Interval::value_type max);
size_t get_vertices_count() const { return m_vertices.size(); }
const PathVertex& get_current_vertex() const { return get_vertex_at(get_current_vertex_id()); }
size_t get_current_vertex_id() const { return static_cast<size_t>(m_view_range.get_visible()[1]); }
const PathVertex& get_vertex_at(size_t id) const {
return (id < m_vertices.size()) ? m_vertices[id] : PathVertex::DUMMY_PATH_VERTEX;
}
float get_estimated_time() const { return m_total_time[static_cast<size_t>(m_settings.time_mode)]; }
float get_estimated_time_at(size_t id) const;
Color get_vertex_color(const PathVertex& vertex) const;
size_t get_extrusion_roles_count() const { return m_extrusion_roles.get_roles_count(); }
std::vector<EGCodeExtrusionRole> get_extrusion_roles() const { return m_extrusion_roles.get_roles(); }
float get_extrusion_role_estimated_time(EGCodeExtrusionRole role) const { return m_extrusion_roles.get_time(role, m_settings.time_mode); }
size_t get_options_count() const { return m_options.size(); }
const std::vector<EOptionType>& get_options() const { return m_options; }
float get_travels_estimated_time() const { return m_travels_time[static_cast<size_t>(m_settings.time_mode)]; }
std::vector<float> get_layers_estimated_times() const { return m_layers.get_times(m_settings.time_mode); }
size_t get_tool_colors_count() const { return m_tool_colors.size(); }
const Palette& get_tool_colors() const { return m_tool_colors; }
void set_tool_colors(const Palette& colors);
size_t get_color_print_colors_count() const { return m_color_print_colors.size(); }
const Palette& get_color_print_colors() const { return m_color_print_colors; }
void set_color_print_colors(const Palette& colors);
const Color& get_extrusion_role_color(EGCodeExtrusionRole role) const;
void set_extrusion_role_color(EGCodeExtrusionRole role, const Color& color);
void reset_default_extrusion_roles_colors();
const Color& get_option_color(EOptionType type) const;
void set_option_color(EOptionType type, const Color& color);
void reset_default_options_colors();
const ColorRange& get_color_range(EViewType type) const;
void set_color_range_palette(EViewType type, const Palette& palette);
float get_travels_radius() const { return m_travels_radius; }
void set_travels_radius(float radius);
float get_wipes_radius() const { return m_wipes_radius; }
void set_wipes_radius(float radius);
size_t get_used_cpu_memory() const;
size_t get_used_gpu_memory() const;
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
Vec3 get_cog_marker_position() const { return m_cog_marker.get_position(); }
float get_cog_marker_scale_factor() const { return m_cog_marker_scale_factor; }
void set_cog_marker_scale_factor(float factor) { m_cog_marker_scale_factor = std::max(factor, 0.001f); }
const Vec3& get_tool_marker_position() const { return m_tool_marker.get_position(); }
float get_tool_marker_offset_z() const { return m_tool_marker.get_offset_z(); }
void set_tool_marker_offset_z(float offset_z) { m_tool_marker.set_offset_z(offset_z); }
float get_tool_marker_scale_factor() const { return m_tool_marker_scale_factor; }
void set_tool_marker_scale_factor(float factor) { m_tool_marker_scale_factor = std::max(factor, 0.001f); }
const Color& get_tool_marker_color() const { return m_tool_marker.get_color(); }
void set_tool_marker_color(const Color& color) { m_tool_marker.set_color(color); }
float get_tool_marker_alpha() const { return m_tool_marker.get_alpha(); }
void set_tool_marker_alpha(float alpha) { m_tool_marker.set_alpha(alpha); }
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
private:
//
// Settings used to render the toolpaths
//
Settings m_settings;
//
// Detected layers
//
Layers m_layers;
//
// Detected extrusion roles
//
ExtrusionRoles m_extrusion_roles;
//
// Detected options
//
std::vector<EOptionType> m_options;
//
// Detected used extruders ids
//
std::map<uint8_t, std::vector<ColorPrint>> m_used_extruders;
//
// Vertices ranges for visualization
//
ViewRange m_view_range;
//
// Detected total moves times
//
std::array<float, TIME_MODES_COUNT> m_total_time{ 0.0f, 0.0f };
//
// Detected travel moves times
//
std::array<float, TIME_MODES_COUNT> m_travels_time{ 0.0f, 0.0f };
//
// Radius of cylinders used to render travel moves segments
//
float m_travels_radius{ DEFAULT_TRAVELS_RADIUS_MM };
//
// Radius of cylinders used to render wipe moves segments
//
float m_wipes_radius{ DEFAULT_WIPES_RADIUS_MM };
//
// Palette used to render extrusion roles
//
std::array<Color, size_t(EGCodeExtrusionRole::COUNT)> m_extrusion_roles_colors;
//
// Palette used to render options
//
std::array<Color, size_t(EOptionType::COUNT)> m_options_colors;
bool m_initialized{ false };
//
// The OpenGL element used to represent all toolpath segments
//
SegmentTemplate m_segment_template;
//
// The OpenGL element used to represent all option markers
//
OptionTemplate m_option_template;
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// The OpenGL element used to represent the center of gravity
//
CogMarker m_cog_marker;
float m_cog_marker_scale_factor{ 1.0f };
//
// The OpenGL element used to represent the tool nozzle
//
ToolMarker m_tool_marker;
float m_tool_marker_scale_factor{ 1.0f };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// cpu buffer to store vertices
//
std::vector<PathVertex> m_vertices;
// Cache for the colors to reduce the need to recalculate colors of all the vertices.
std::vector<float> m_vertices_colors;
//
// Variables used for toolpaths visibiliity
//
BitSet<> m_valid_lines_bitset;
//
// Variables used for toolpaths coloring
//
std::optional<Settings> m_settings_used_for_ranges;
ColorRange m_height_range;
ColorRange m_width_range;
ColorRange m_speed_range;
ColorRange m_actual_speed_range;
ColorRange m_fan_speed_range;
ColorRange m_temperature_range;
ColorRange m_volumetric_rate_range;
ColorRange m_actual_volumetric_rate_range;
std::array<ColorRange, COLOR_RANGE_TYPES_COUNT> m_layer_time_range{
ColorRange(EColorRangeType::Linear), ColorRange(EColorRangeType::Logarithmic)
};
Palette m_tool_colors;
Palette m_color_print_colors;
//
// OpenGL shaders ids
//
unsigned int m_segments_shader_id{ 0 };
unsigned int m_options_shader_id{ 0 };
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
unsigned int m_cog_marker_shader_id{ 0 };
unsigned int m_tool_marker_shader_id{ 0 };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Caches for OpenGL uniforms id for segments shader
//
int m_uni_segments_view_matrix_id{ -1 };
int m_uni_segments_projection_matrix_id{ -1 };
int m_uni_segments_camera_position_id{ -1 };
int m_uni_segments_positions_tex_id{ -1 };
int m_uni_segments_height_width_angle_tex_id{ -1 };
int m_uni_segments_colors_tex_id{ -1 };
int m_uni_segments_segment_index_tex_id{ -1 };
//
// Caches for OpenGL uniforms id for options shader
//
int m_uni_options_view_matrix_id{ -1 };
int m_uni_options_projection_matrix_id{ -1 };
int m_uni_options_positions_tex_id{ -1 };
int m_uni_options_height_width_angle_tex_id{ -1 };
int m_uni_options_colors_tex_id{ -1 };
int m_uni_options_segment_index_tex_id{ -1 };
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
//
// Caches for OpenGL uniforms id for cog marker shader
//
int m_uni_cog_marker_world_center_position{ -1 };
int m_uni_cog_marker_scale_factor{ -1 };
int m_uni_cog_marker_view_matrix{ -1 };
int m_uni_cog_marker_projection_matrix{ -1 };
//
// Caches for OpenGL uniforms id for tool marker shader
//
int m_uni_tool_marker_world_origin{ -1 };
int m_uni_tool_marker_scale_factor{ -1 };
int m_uni_tool_marker_view_matrix{ -1 };
int m_uni_tool_marker_projection_matrix{ -1 };
int m_uni_tool_marker_color_base{ -1 };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#ifdef ENABLE_OPENGL_ES
class TextureData
{
public:
void init(size_t vertices_count);
void set_positions(const std::vector<Vec3>& positions);
void set_heights_widths_angles(const std::vector<Vec3>& heights_widths_angles);
void set_colors(const std::vector<float>& colors);
void set_enabled_segments(const std::vector<uint32_t>& enabled_segments);
void set_enabled_options(const std::vector<uint32_t>& enabled_options);
void reset();
size_t get_count() const { return m_count; }
std::pair<unsigned int, size_t> get_positions_tex_id(size_t id) const;
std::pair<unsigned int, size_t> get_heights_widths_angles_tex_id(size_t id) const;
std::pair<unsigned int, size_t> get_colors_tex_id(size_t id) const;
std::pair<unsigned int, size_t> get_enabled_segments_tex_id(size_t id) const;
std::pair<unsigned int, size_t> get_enabled_options_tex_id(size_t id) const;
size_t get_enabled_segments_count() const;
size_t get_enabled_options_count() const;
size_t max_texture_capacity() const { return m_width * m_height; }
size_t get_used_gpu_memory() const;
private:
//
// Texture width
//
size_t m_width{ 0 };
//
// Texture height
//
size_t m_height{ 0 };
//
// Count of textures
//
size_t m_count{ 0 };
//
// Caches for size of data sent to gpu, in bytes
//
size_t m_positions_size{ 0 };
size_t m_height_width_angle_size{ 0 };
size_t m_colors_size{ 0 };
size_t m_enabled_segments_size{ 0 };
size_t m_enabled_options_size{ 0 };
struct TexIds
{
//
// OpenGL texture to store positions
//
std::pair<unsigned int, size_t> positions{ 0, 0 };
//
// OpenGL texture to store heights, widths and angles
//
std::pair<unsigned int, size_t> heights_widths_angles{ 0, 0 };
//
// OpenGL texture to store colors
//
std::pair<unsigned int, size_t> colors{ 0, 0 };
//
// OpenGL texture to store enabled segments
//
std::pair<unsigned int, size_t> enabled_segments{ 0, 0 };
//
// OpenGL texture to store enabled options
//
std::pair<unsigned int, size_t> enabled_options{ 0, 0 };
};
std::vector<TexIds> m_tex_ids;
};
TextureData m_texture_data;
#else
//
// OpenGL buffers to store positions
//
unsigned int m_positions_buf_id{ 0 };
unsigned int m_positions_tex_id{ 0 };
//
// OpenGL buffers to store heights, widths and angles
//
unsigned int m_heights_widths_angles_buf_id{ 0 };
unsigned int m_heights_widths_angles_tex_id{ 0 };
//
// OpenGL buffers to store colors
//
unsigned int m_colors_buf_id{ 0 };
unsigned int m_colors_tex_id{ 0 };
//
// OpenGL buffers to store enabled segments
//
unsigned int m_enabled_segments_buf_id{ 0 };
unsigned int m_enabled_segments_tex_id{ 0 };
size_t m_enabled_segments_count{ 0 };
//
// OpenGL buffers to store enabled options
//
unsigned int m_enabled_options_buf_id{ 0 };
unsigned int m_enabled_options_tex_id{ 0 };
size_t m_enabled_options_count{ 0 };
//
// Caches for size of data sent to gpu, in bytes
//
size_t m_positions_tex_size{ 0 };
size_t m_height_width_angle_tex_size{ 0 };
size_t m_colors_tex_size{ 0 };
size_t m_enabled_segments_tex_size{ 0 };
size_t m_enabled_options_tex_size{ 0 };
#endif // ENABLE_OPENGL_ES
void update_view_full_range();
void update_color_ranges();
void update_heights_widths();
void render_segments(const Mat4x4& view_matrix, const Mat4x4& projection_matrix, const Vec3& camera_position);
void render_options(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
void render_cog_marker(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
void render_tool_marker(const Mat4x4& view_matrix, const Mat4x4& projection_matrix);
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
};
} // namespace libvgcode
#endif // VGCODE_VIEWERIMPL_HPP