code:
#ifndef _threadControl_H
#define _threadControl_H

#include <thread>
#include <vector>

struct threadControl {
    std::vector < std::thread* > threads;
};

#endif // threadControl_H

repo_name: assblast/AME

license: unknown


code:
/*
 * Rotate writed by instaruction from
 * http://blog.wolfire.com/2010/07/Linear-algebra-for-game-developers-part-4
 *
 * writed by Alexey Matveev (AlMat26)
*/

#include <GLES3/gl3.h>

#include <mesh/mesh.h>
#include <app/modules/thirdParty/OBJLoader.h>

enum MeshBufferPositions {
    POSITION_VB,
    TEXCOORD_VB,
	NORMAL_VB,
	INDEX_VB
};

Vertex::Vertex ( glm::vec3 position, glm::vec2 textureCoordinates, glm::vec3 normal ) {

    this -> position = position;
    this -> textureCoordinates = textureCoordinates;
    this -> normal = normal;
}

glm::vec3* Vertex::getPosition () {

    return &this -> position;
}

glm::vec2* Vertex::getTextureCoordinates () {

    return &this -> textureCoordinates;
}

glm::vec3* Vertex::getNormal () {

    return &this -> normal;
}

Mesh::Mesh ( Vertex* vertices, unsigned int verticesCount, unsigned int* indices, unsigned int indicesCount ) {

    Model model;

    for ( unsigned int i = 0; i < verticesCount; i++ ) {

        model.positions.push_back ( *vertices [i].getPosition () );
        model.textureCoordinates.push_back ( *vertices [i].getTextureCoordinates () );
        model.normals.push_back ( *vertices [i].getNormal () );
    }

    for(unsigned int i = 0; i < indicesCount; i++) {

        model.indices.push_back ( indices [i] );
    }

    InitMesh ( model );
}

Mesh::Mesh ( std::string filename ) {
    InitMesh ( OBJModel ( filename ).ToIndexedModel () );
}

void Mesh::InitMesh ( const Model& model) {
    m_numIndices = model.indices.size();

    glGenVertexArrays ( 1, &m_vertexArrayObject );
    glBindVertexArray ( m_vertexArrayObject );

    glGenBuffers( BUFFERS_COUNT, m_vertexArrayBuffers );

    glBindBuffer ( GL_ARRAY_BUFFER, m_vertexArrayBuffers [ POSITION_VB ] );
    glBufferData ( GL_ARRAY_BUFFER, sizeof ( model.positions [0] ) * model.positions.size (), &model.positions [0], GL_STATIC_DRAW );
    glEnableVertexAttribArray ( 0 );
    glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );

    glBindBuffer ( GL_ARRAY_BUFFER, m_vertexArrayBuffers [ TEXCOORD_VB ] );
    glBufferData ( GL_ARRAY_BUFFER, sizeof ( model.textureCoordinates [0] ) * model.textureCoordinates.size (), &model.textureCoordinates [0], GL_STATIC_DRAW );
    glEnableVertexAttribArray ( 1 );
    glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, 0, 0 );

    glBindBuffer ( GL_ARRAY_BUFFER, m_vertexArrayBuffers [ NORMAL_VB ]);
    glBufferData ( GL_ARRAY_BUFFER, sizeof ( model.normals [0] ) * model.normals.size (), &model.normals [0], GL_STATIC_DRAW );
    glEnableVertexAttribArray ( 2 );
    glVertexAttribPointer ( 2, 3, GL_FLOAT, GL_FALSE, 0, 0 );

    glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers [ INDEX_VB ] );
    glBufferData ( GL_ELEMENT_ARRAY_BUFFER, sizeof ( model.indices [0] ) * model.indices.size (), &model.indices [0], GL_STATIC_DRAW);

    glBindVertexArray ( 0 );
}

void Mesh::Draw () {

    glBindVertexArray ( m_vertexArrayObject );

	glDrawElements ( GL_TRIANGLES, m_numIndices, GL_UNSIGNED_INT, 0 );
    //glDrawElementsBaseVertex ( GL_TRIANGLES, m_numIndices, GL_UNSIGNED_INT, 0, 0 );

    glBindVertexArray ( 0 );
}

Mesh::~Mesh () {

    glDeleteBuffers ( BUFFERS_COUNT, m_vertexArrayBuffers );
    glDeleteVertexArrays ( 1, &m_vertexArrayObject );
}


code:
#ifndef _MESHPOINTS_H
#define _MESHPOINTS_H

#include <vector>
#include <cmath>
#include <string>
#include <glm/glm.hpp>

#include <app/ameTypes.h>
#include <render/output/material.h>

struct Vertex {
public:

    Vertex ( glm::vec3 position, glm::vec2 textureCoordinates, glm::vec3 normal );

    glm::vec3* getPosition ();
    glm::vec2* getTextureCoordinates ();
    glm::vec3* getNormal ();

private:

    glm::vec3 position;
    glm::vec2 textureCoordinates;
    glm::vec3 normal;
};

struct Model {
    std::vector <glm::vec3> positions;
    std::vector <glm::vec2> textureCoordinates;
    std::vector <glm::vec3> normals;
    std::vector <unsigned int> indices;

    void calculateNormals ();
};

class Mesh {
public:

    Mesh ( Vertex* vertices, unsigned int verticesCount, unsigned int* indices, unsigned int indicesCount );
    Mesh ( std::string filename );

    void Draw ();

    ~Mesh ();

private:

    void InitMesh ( const Model& model );

    static const unsigned int BUFFERS_COUNT = 4;
    unsigned int m_vertexArrayObject;
	unsigned int m_vertexArrayBuffers [ BUFFERS_COUNT ];
	unsigned int m_numIndices;
};

#endif // _MESHPOINTS_H


code:
#ifndef _OBJECT_H
#define _OBJECT_H

#include <mesh/transform.h>
#include <mesh/mesh.h>

struct Object {
    Transform transform;
    Mesh* mesh = nullptr;
};

#endif // _OBJECT_H


code:
#include <mesh/physics.h>
#include <mesh/object.h>
#include <app/Atime.h>
#include <app/ameTypes.h>

#include <vector>
#include <math.h>

Physics::Physics ( Object& thisObj, Atime& time, std::vector <Object*>& objects ) {
    Physics::object = &thisObj;
    Physics::time = &time;
    Physics::objects = objects;
}

/*
 * Идет цикл, количество итераций которого равно размеру массива всех объектов,
 * который иницилизировал разработчик в конструкторе класса Physics. В нём создаётся
 * вектор трехмерного пространства, в которое мы записываем координаты объекта, с
 * которым собираемся сравнивать позиции, затем вещественную переменную double, в
 * которой будет храниться расстояние от нашего объекта до чужого.
 *
 * Далее переменной дистанции присвается квадратный корень из суммы разностей
 * координат по каждой оси.
 *
 * Потом идёт проверка - объект, с которым будет производиться работа находится
 * в отрицательных координатах или положительных. Если он находится на большем
 * расстоянии, чем проверка коллизии (collisionRadius), то объект пропускается,
 * а цикл продолжается, иначе вызывается функция, которая будет уже просчитывать
 * коллизию по полигонам.
*/
void Physics::Update () {
    for ( int i = 0; i <= objects.size (); i++ ) {
        ame::vec3 objPosition; //позиция объекта, с которым мы будем работать
        double distance;

        objPosition.x = objects [i] -> transform.getLocation().x;
        objPosition.y = objects [i] -> transform.getLocation().y;
        objPosition.z = objects [i] -> transform.getLocation().z;

        //formula example: https://algebra24.ru/rasstojanie-mezhdu-dvumja-tochkami
        distance = sqrt ( pow ( object->transform.getLocation().x - objects [i]->transform.getLocation().x, 2 ) +
            pow ( object->transform.getLocation().y - objects [i]->transform.getLocation().y, 2 ) +
            pow ( object->transform.getLocation().z - objects [i]->transform.getLocation().z, 2 )
        );
        /*
        if ( distance > objects [i] -> collider.collisionRadius ) {
            continue;
        } else if ( -distance > objects [i] -> collider.collisionRadius ) {
            continue;
        } else {
            //
        }*/
    }
}


code:
#ifndef PHYSICS_H
#define PHYSICS_H

#include <mesh/object.h>
#include <mesh/mesh.h>
#include <app/Atime.h>

#include <vector>

class Physics {
public:
    //setup block (this object, world time, объекты, с которыми надо просчитывать коллизию)
    Physics ( Object&, Atime&, std::vector <Object*>& );

    //update block
    void Update ();

private:
    //object and world time
    Atime* time;
    Object* object;
    Mesh* collider;
    std::vector <Object*> objects;

    //блок, определяющий пересечения прямых
    double dot[2]; //точка пересечения
    bool dotEnded; //просчитано ли пересечение, чтобы вызвать функцию получения точки пересечения
    bool cross ( std::vector <double> & );
};

#endif


code:
#include <mesh/transform.h>
#include <mesh/mesh.h>
#include <app/ameTypes.h>

#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

Transform::Transform ( glm::vec3 position, glm::vec3 rotation, glm::vec3 scale ) {

    this -> position = position;
    this -> rotation = rotation;
    this -> scale = scale;
}

Transform::Transform () {

    position = glm::vec3 (0, 0, 0);
    rotation = glm::vec3 (0, 0, 0);
    scale = glm::vec3 (1, 1, 1);
}

void Transform::setX ( double x ) {
    position.x = x;
}

void Transform::setY ( double y ) {
    position.y = y;
}

void Transform::setZ ( double z ) {
    position.z = z;
}

glm::vec3 Transform::getLocation () {
    return this -> position;
}

glm::vec3 Transform::getRotation () {
    return this -> rotation;
}

glm::vec3 Transform::getScale () {
    return this -> scale;
}

void Transform::setPosition ( glm::vec3 axis ) {
    position.x = axis.x;
    position.y = axis.y;
    position.z = axis.z;
}

void Transform::translate ( glm::vec3 direction ) {
    position.x += direction.x;
    position.y += direction.y;
    position.z += direction.z;
}

void Transform::setRotation ( glm::vec3 deg ) {
    rotation = deg;
}
void Transform::rotate ( glm::vec3 deg ) {
    rotation.x += deg.x;
    rotation.y += deg.y;
    rotation.z += deg.z;
}

void Transform::setScale ( glm::vec3 scale ) {
    this -> scale = scale;
}

glm::mat4 Transform::getModel () {

    glm::mat4 positionMatrix = glm::translate ( this -> position );

    glm::mat4 scaleMatrix = glm::scale ( this -> scale );

    glm::mat4 rotationX = glm::rotate ( this -> rotation.x, glm::vec3 ( 1.0, 0.0, 0.0 ) );
    glm::mat4 rotationY = glm::rotate ( this -> rotation.y, glm::vec3 ( 0.0, 1.0, 0.0 ) );
    glm::mat4 rotationZ = glm::rotate ( this -> position.z, glm::vec3 ( 0.0, 0.0, 1.0 ) );

    glm::mat4 rotationMatrix = rotationX * rotationY * rotationZ;

    return positionMatrix * rotationMatrix * scaleMatrix;
}

glm::mat4 Transform::GetMatrixViewProjection ( Camera& camera ) {

    glm::mat4 viewProjection = camera.getViewProjection ();
    glm::mat4 model = getModel ();

    return viewProjection * model;
}


code:
/*
 * 1.0 = 1m
 *  => 0.01 = 1cm; 1000.0 = 1km
*/

#ifndef _TRANSFORM_H
#define _TRANSFORM_H

#include <mesh/mesh.h>
#include <app/ameTypes.h>
#include <render/enviroment/camera.h>

#include <glm/glm.hpp>

class Transform {
public:
    Transform ( glm::vec3 position, glm::vec3 rotation, glm::vec3 scale );
    Transform ();

    void setX ( double x );
    void setY ( double y );
    void setZ ( double z );

    void setPosition ( glm::vec3 );
    void translate( glm::vec3 direction );

    void setRotation ( glm::vec3 );
    void rotate ( glm::vec3 );

    void setScale ( glm::vec3 );

    glm::vec3 getLocation ();
    glm::vec3 getRotation ();
    glm::vec3 getScale ();

    glm::mat4 getModel ();
    glm::mat4 GetMatrixViewProjection ( Camera &camera );

private:

    glm::vec3 position;
    glm::vec3 rotation;
    glm::vec3 scale;
};

#endif // _TRANSFORM_H


code:
#include <render/UI/text/font.h>

#include <iostream>
#include <string>
#include <ft2build.h>
#include FT_FREETYPE_H

Font::Font ( std::string pathToFont ) {
	if(FT_Init_FreeType(&this->m_lib))
	{
		std::cerr << "Failed to init FreeType" << std::endl;
	}

	if(pathToFont.empty())
	{
		if(FT_New_Face(this->m_lib, "./fonts/OpenSans-Regular.ttf", 0, &this->m_face))
		{
			std::cerr << "Unable to load default font" << std::endl;
		}
	}
	else
	{
		if(FT_New_Face(this->m_lib, pathToFont.c_str(), 0, &this->m_face))
		{
			std::cerr << "Unable to load '" << pathToFont << "' font" << std::endl;
		}
	}

	FT_Set_Pixel_Sizes(this->m_face, 0, 48);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	for(uint8_t i = 0; i < 128; i++)
	{
		if(FT_Load_Char(this->m_face, i, FT_LOAD_RENDER))
		{
			std::cerr << "Failed to load character " << i << std::endl;
			continue;
		}

		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexImage2D(
			GL_TEXTURE_2D,
			0,
			GL_RED,
			this->m_face->glyph->bitmap.width,
			this->m_face->glyph->bitmap.rows,
			0,
			GL_RED,
			GL_UNSIGNED_BYTE,
			this->m_face->glyph->bitmap.buffer
		);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		ft_char_t ch =
		{
			texture,
			glm::ivec2(this->m_face->glyph->bitmap.width, this->m_face->glyph->bitmap.rows),
			glm::ivec2(this->m_face->glyph->bitmap_left, this->m_face->glyph->bitmap_top),
			static_cast<unsigned int>(this->m_face->glyph->advance.x)
		};

		this->alphabet.insert(std::pair<GLchar, ft_char_t>(i, ch));
	}
}

Font::~Font () {
	FT_Done_Face(this->m_face);
	FT_Done_FreeType(this->m_lib);
}


code:
#ifndef FONT_H
#define FONT_H

#include <string>
#include <map>
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
#include <ft2build.h>
#include FT_FREETYPE_H

struct ft_char_t
{
	GLuint textureID;
	glm::ivec2 size;
	glm::ivec2 bearing;
	GLuint advance;
};

class Font {
public:
	Font ( std::string pathToFont = nullptr );
	~Font ();

	std::map<GLchar, ft_char_t> alphabet;

private:
	FT_Library m_lib;
	FT_Face m_face;
};

#endif


code:
#include <render/UI/text/text.h>
#include <render/UI/text/font.h>

#include <string>
#include <freetype2/ft2build.h>
#include <glm/glm.hpp>
#include <render/output/shader.h>

Text::Text(std::string& str, float scale, glm::vec2 pos, glm::vec3 color, uint32_t matrix_w, uint32_t matrix_h)
{
	this->m_text = str;
	this->m_scale = scale;
	this->m_pos = pos;
	this->m_color = color;
	this->m_projection = glm::ortho(0.0f, static_cast<float>(matrix_w), 0.0f, static_cast<float>(matrix_h));
	this->m_shader->Bind();
	glUniformMatrix4fv(glGetUniformLocation(this->m_shader->GetProgram(), "projection"), 1, GL_FALSE, glm::value_ptr(this->m_projection));
}

void Text::Print () {
	if(this->m_text.empty())
	{
		return;
	}

    this->m_shader->Bind();
    glUniform3f(glGetUniformLocation(this->m_shader->GetProgram(), "textColor"),
    								 this->m_color.x,
    								 this->m_color.y,
    								 this->m_color.z);

    glUniform1f(glGetUniformLocation(this->m_shader->GetProgram(), "transparency"), this->m_transparency);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(this->VAO);

    std::string::const_iterator c;
    for (c = this->m_text.begin(); c != this->m_text.end(); c++)
    {
        ft_char_t ch = this->m_font.alphabet[*c];

        GLfloat xpos = this->m_pos.x + ch.bearing.x * this->m_scale;
        GLfloat ypos = this->m_pos.y - (ch.size.y - ch.bearing.y) * this->m_scale;

        GLfloat w = ch.size.x * this->m_scale;
        GLfloat h = ch.size.y * this->m_scale;

        GLfloat vertices[6][4] = {
            { xpos, ypos + h, 0.0, 0.0 },
            { xpos, ypos, 0.0, 1.0 },
            { xpos + w, ypos, 1.0, 1.0 },
            { xpos, ypos + h, 0.0, 0.0 },
            { xpos + w, ypos, 1.0, 1.0 },
            { xpos + w, ypos + h, 1.0, 0.0 }
        };

        glBindTexture(GL_TEXTURE_2D, ch.textureID);

        glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glDrawArrays(GL_TRIANGLES, 0, 6);

        this->m_pos.x += (ch.advance >> 6) * this->m_scale;
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}


code:
#ifndef TEXT_H
#define TEXT_H

#include <string>
#include <map>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <render/output/shader.h>
#include <render/UI/text/font.h>

class Text {
public:
	Text ( std::string &str, float scale, glm::vec2 pos, glm::vec3 color, uint32_t matrix_w, uint32_t matrix_h );
	Text ( Shader text_sh, std::string str );

	void Print ();
	void Print ( std::string str );

private:
	Shader* m_shader = new Shader ( "./res/text" );

	Font m_font;

	GLfloat   m_scale;
	glm::vec2 m_pos;
	glm::vec3 m_color;
	float     m_transparency = 1.0f;

	GLuint VAO, VBO;

	std::string m_text;

	glm::mat4 m_projection;
};

#endif


code:
#include <render/enviroment/camera.h>

#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

Camera::Camera ( glm::vec3 position, double fieldOfView, double aspect, double zNear, double zFar ) {

    this -> mPosition = position;
    this -> mForward = glm::vec3 ( 0.0, 0.0, 1.0 );
    this -> mUp = glm::vec3 ( 0.0, 1.0, 0.0 );

    this -> fieldOfView = fieldOfView;
    this -> aspect = aspect;
    this -> zNear = zNear;
    this -> zFar = zFar;

    this -> yaw = 90.0;
    this -> pitch = 0.0;

    this -> applyChanges ();
}

void Camera::setPosition ( glm::vec3 position ) {

    this -> mPosition = position;
}

void Camera::setCameraTarget ( glm::vec3 target ) {
    /*
     * вычитание делаем, чтобы сделать z координату положительной,
     * поскольку по соглашению openGL камера указывает вдоль отрицательной оси z
    */
    this -> mDirection = glm::normalize ( this -> mPosition - target );

    glm::vec3 up = glm::vec3 ( 0.0f, 1.0f, 0.0f );
    this -> mRight = glm::normalize ( glm::cross ( up, this -> mDirection ) );

    this -> mUp = glm::cross ( this -> mDirection, this -> mRight );
}

void Camera::setCameraTarget ( Amouse* mouse ) {

    this -> yaw += mouse -> offsetX;
    this -> pitch += mouse -> offsetY;

    if ( this -> pitch > 89.0 ) {

        this -> pitch = 89.0;

    } else if ( this -> pitch < -89.0 ) {

        this -> pitch = -89.0;
    }

    glm::vec3 front;

    front.x = cos ( glm::radians ( this -> yaw ) ) * cos ( glm::radians ( this -> pitch ) );
    front.y = sin ( glm::radians ( this -> pitch ) );
    front.z = sin ( glm::radians ( this -> yaw ) ) * cos ( glm::radians ( this -> pitch ) );

    this -> mForward = glm::normalize ( front );
}

void Camera::setFieldOfView ( double FOV ) {

    this -> fieldOfView = FOV;
}

void Camera::setAspect ( double aspect ) {

    this -> aspect = aspect;
}

void Camera::setNearClipping ( double zNear ) {

    this -> zNear = zNear;
}

void Camera::setFarClipping ( double zFar ) {

    this -> zFar = zFar;
}

glm::vec3 Camera::getPosition () {

    return this -> mPosition;
}

glm::vec3 Camera::getCameraTarget () {

    return this -> mDirection;
}

double Camera::getFieldOfView () {

    return this -> fieldOfView;
}

double Camera::getAspect () {

    return this -> aspect;
}

double Camera::getNearClipping () {

    return this -> zNear;
}

double Camera::getFarClipping () {

    return this -> zFar;
}

glm::mat4 Camera::getViewProjection () {

    return mProjection * mView;
}

void Camera::applyChanges () {

    this -> mProjection = glm::perspective ( fieldOfView, aspect, zNear, zFar );

    this -> mView = glm::lookAt ( this -> mPosition,
                                        this -> mPosition + this -> mForward,
                                        this -> mUp );
}


code:
#ifndef CAMERA_H
#define CAMERA_H

#include <app/ameTypes.h>
#include <app/modules/Ainput.h>

#include <glm/glm.hpp>

class Camera {

public:

    Camera ( glm::vec3 position, double fieldOfView, double aspect, double zNear, double zFar );

    void setPosition ( glm::vec3 position );
    void setCameraTarget ( glm::vec3 target );
    void setCameraTarget ( Amouse* );

    void setFieldOfView ( double FOV );
    void setAspect ( double aspect );
    void setNearClipping ( double zNear );
    void setFarClipping ( double zFar );

    glm::vec3 getPosition ();
    glm::vec3 getCameraTarget ();

    double getFieldOfView ();
    double getAspect ();
    double getNearClipping ();
    double getFarClipping ();

    void applyChanges ();

    glm::mat4 getViewProjection ();

private:

    glm::mat4 mProjection;
    glm::mat4 mView;
    glm::vec3 mPosition;
    glm::vec3 mDirection;
    glm::vec3 mForward;
    glm::vec3 mRight;
    glm::vec3 mUp;

    double fieldOfView;
    double aspect;
    double zNear;
    double zFar;

    double yaw, pitch; //for mouse direction
};

#endif


code:
#ifndef LIGHT_H
#define LIGHT_H

#include <app/ameTypes.h>

struct Light {
    unsigned int force;
    ame::vec3 position;
    ame::vec3 color;
};

struct SunLight: Light {
    ame::vec3 direction;
};

struct DirectLight: Light {
    ame::vec3 direction;
    double radius;
    double diffusion;
};

#endif


code:
#ifndef SCENE_H
#define SCENE_H

#include <vector>

#include <mesh/object.h>
#include <render/enviroment/light.h>

struct Scene {
    std::vector <Object*> objects;
    std::vector <Light*> lights;
    std::vector <SunLight*> sunLights;
    std::vector <DirectLight*> directLights;
};

#endif


code:
#version 120

varying vec2 texCoord0;
varying vec3 normal0;

uniform sampler2D sampler;
uniform vec3 lightDirection;

void main()
{
	gl_FragColor = texture2D ( sampler, texCoord0 ) *
		clamp ( dot ( -vec3 (0, 0, 1), normal0 ), 0.0, 1.0);
}


code:
#version 120

attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;

varying vec2 texCoord0;
varying vec3 normal0;

uniform mat4 u_MatrixViewProjection;
uniform mat4 u_Normal;

void main()
{
	gl_Position = u_MatrixViewProjection * vec4 ( position, 1.0 );
	texCoord0 = texCoord;
	normal0 = ( u_Normal * vec4 ( normal, 0.0 ) ).xyz;
}


code:
#version 120
in vec2 TexCoords;
out vec4 color;

uniform sampler2D text;
uniform vec3 color;
uniform float transparency;

void main()
{
    vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
    color = vec4(color, transparency) * sampled;
}


code:
#version 120
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex_coord>
out vec2 TexCoords;

uniform mat4 projection;

void main()
{
    gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
    TexCoords = vertex.zw;
}


code:
#include <GLES3/gl3.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <iostream>

#include <render/output/OGLRender.h>
#include <mesh/mesh.h>
#include <app/Atime.h>
#include <app/Application.h>

enum {
    POSITION_VB,
    NUM_BUFFERS
};

void OGLRender::mainCycle () {
    //if using GLFW
    if ( (*app).openGLTools.OpenGLContext == OGLC_GLFW ) {

        while ( !window -> isClosed () && (*app).running ) {
            glfwPollEvents ();
            glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

            (*app).update ();

            window -> Update();
        }

    //if using Qt tools
    } else if ( (*app).openGLTools.OpenGLContext == OGLC_GLFW ) {

        while ( !(*app).openGLTools.glWindowShouldClose && (*app).running ) {
            glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

            (*app).update ();

            (*app).openGLTools.glSwapBuffers ();
        }
    }
}

void OGLRender::joinToMainCycle () {
    mainCycle ();
}

OGLRender::OGLRender ( Application* appPtr, Window* win ) {
    app = appPtr;
    window = win;
}


code:
#ifndef OGLRENDER_H
#define OGLRENDER_H

#include <app/Application.h>
#include <app/modules/threadControl.h>
#include <mesh/mesh.h>
#include <render/output/window.h>

class OGLRender {
public:
    OGLRender ( Application* app, Window* win );
    //void Draw ( Mesh& );
    void joinToMainCycle ();

private:
    Window* window;
    Application* app;

    void mainCycle ();
};

#endif


code:
/*
 * RenderManager class allows you to split render calls into threads
 */

#ifndef RENDERMANAGER_H
#define RENDERMANAGER_H

#include <vector>

#include <mesh/mesh.h>
#include <app/modules/threadControl.h>

#include <render/output/OGLRender.h>

class RenderManager {
public:
    RenderManager ( OGLRender* );

    void addToQueue ( Mesh* );
    void addQueue ( std::vector < Mesh* > );
    void startRenderObjects ();

private:
    std::vector <Mesh> queue;
    threadControl threads;

    OGLRender* GLRender;
};

#endif


code:
#ifndef MATERIAL_H
#define MATERIAL_H

#include <vector>
#include <glm/glm.hpp>

enum MaterialType {
    MATERIAL_NONE,
    MATERIAL_METALIC,
    MATERIAL_DIFFUSION,
    MATERIAL_EMISSION
};

enum DrawType {
    Polygon, Line, Point
};

struct Material {
    MaterialType materialType;
    DrawType drawType;
    double diffusion; //0.0 - 1.0
    glm::vec4 color;
    std::vector < glm::vec2 > textureCoordinate;
};

#endif


code:
#include <render/output/shader.h>

#include <string>
#include <iostream>
#include <fstream>
#include <GLES3/gl3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

static std::string LoadShader ( const std::string& filename );
static void CheckShaderError ( GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage );
static GLuint CreateShader ( const std::string& text, GLenum shaderType );

Shader::Shader ( const std::string& filename ) {

    m_program = glCreateProgram ();
    m_shaders [0] = CreateShader ( LoadShader ( filename + ".vs" ), GL_VERTEX_SHADER );
    m_shaders [1] = CreateShader ( LoadShader ( filename + ".fs" ), GL_FRAGMENT_SHADER );

    for ( unsigned int i = 0; i < NUM_SHADERS; i++ ) {
        glAttachShader ( m_program, m_shaders [i] );
    }

    glBindAttribLocation ( m_program, 0, "position" );

    glLinkProgram ( m_program );
    CheckShaderError ( m_program, GL_LINK_STATUS, true, "Error: Program linking failed:" );

    glValidateProgram ( m_program );
    CheckShaderError ( m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid:" );
}

Shader::Shader ( const std::string vertexShaderSource, const std::string fragmentShaderSource ) {

    m_program = glCreateProgram ();
    m_shaders [0] = CreateShader ( vertexShaderSource, GL_VERTEX_SHADER );
    m_shaders [1] = CreateShader ( fragmentShaderSource, GL_FRAGMENT_SHADER );

    for ( unsigned int i = 0; i < NUM_SHADERS; i++ ) {
        glAttachShader ( m_program, m_shaders [i] );
    }

    glBindAttribLocation ( m_program, 0, "position" );
    glBindAttribLocation ( m_program, 1, "texCoord" );

    glLinkProgram ( m_program );
    CheckShaderError ( m_program, GL_LINK_STATUS, true, "Error: Program linking failed:" );

    glValidateProgram ( m_program );
    CheckShaderError ( m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid:" );
}

void Shader::Bind () {
    glUseProgram ( m_program );
}

void Shader::SetUniform ( std::string name, double value ) {

    GLuint u_location = glGetUniformLocation ( this -> m_program, name.c_str () );
    glUniform1f ( u_location, value );
}

void Shader::SetUniform ( std::string name, glm::vec2 value ) {

    GLuint u_location = glGetUniformLocation ( this -> m_program, name.c_str () );
    glUniform2f ( u_location, value.x, value.y );
}

void Shader::SetUniform ( std::string name, glm::vec3 value ) {

    GLuint u_location = glGetUniformLocation ( this -> m_program, name.c_str () );
    glUniform3f ( u_location, value.x, value.y, value.z );
}

void Shader::SetUniform ( std::string name, glm::vec4 value ) {

    GLuint u_location = glGetUniformLocation ( this -> m_program, name.c_str () );
    glUniform4f ( u_location, value.x, value.y, value.z, value.t );
}

void Shader::Update ( Transform& transform, Camera& camera ) {

    glm::mat4 MatrixViewProjection = transform.GetMatrixViewProjection ( camera );
	glm::mat4 Normal = transform.getModel ();

    GLuint u_MVPLocation = glGetUniformLocation ( this -> m_program, "u_MatrixViewProjection" );
    GLuint u_NormalLocation = glGetUniformLocation ( this -> m_program, "u_Normal" );
    GLuint u_lightDirection = glGetUniformLocation ( this -> m_program, "u_lightDirection" );

    glUniformMatrix4fv ( u_MVPLocation, 1, GL_FALSE, &MatrixViewProjection [0] [0] );
	glUniformMatrix4fv ( u_NormalLocation, 1, GL_FALSE, &Normal [0] [0] );
	glUniform3f ( u_lightDirection, 0.0f, 0.0f, 1.0f );
}

static GLuint CreateShader ( const std::string& text, GLenum shaderType ) {

    GLuint shader = glCreateShader ( shaderType );

    if ( shader == 0 ) {
        std::cerr << "Error: Shader creation failed" << std::endl;
    }

    const GLchar* shaderSourceStrings [1];
    int shaderSourceLengths = text.length ();

    shaderSourceStrings [0] = text.c_str ();

    glShaderSource ( shader, 1, shaderSourceStrings, &shaderSourceLengths );
    glCompileShader ( shader );

    CheckShaderError ( shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed:" );

    return shader;
}

static std::string LoadShader ( const std::string& filename ) {

    std::ifstream file;
    file.open ( (filename).c_str() );

    std::string output;
    std::string line;

    if ( file.is_open () ) {
        while ( file.good () ) {
            getline ( file, line );
            output.append ( line + "\n" );
        }
    } else {
        std::cerr << "Unable to load shader: " << filename << std::endl;
    }

    return output;
}

static void CheckShaderError ( GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage ) {

    GLint success = 0;
    GLchar error [1024] = { 0 };

    if ( isProgram ) {
        glGetProgramiv ( shader, flag, &success );
    } else {
        glGetShaderiv ( shader, flag, &success );
    }

    if ( success == GL_FALSE ) {
        if ( isProgram ) {
            glGetProgramInfoLog ( shader, sizeof ( error ), NULL, error );
        } else {
            glGetShaderInfoLog ( shader, sizeof ( error ), NULL, error );
        }
        std::cerr << errorMessage << ": '" << error << "'" << std::endl;
    }
}

GLuint Shader::GetProgram ()
{
    return this->m_program;
}

Shader::~Shader () {

    for ( unsigned int i = 0; i < NUM_SHADERS; i++) {

        glDetachShader ( m_program, m_shaders [i] );
        glDeleteShader ( m_shaders [i] );
    }

    glDeleteProgram ( m_program );
}


code:
#ifndef SHADER_H
#define SHADER_H

#include <app/ameTypes.h>
#include <mesh/transform.h>
#include <render/enviroment/camera.h>

#include <string>
#include <GLES3/gl3.h>
#include <glm/glm.hpp>

class Shader {
public:
    Shader ( const std::string& filename );
    Shader ( const std::string vertexShaderSource, const std::string fragmentShaderSource );

    void Bind ();
    void SetUniform ( std::string name, double value );
    void SetUniform ( std::string name, glm::vec2 value );
    void SetUniform ( std::string name, glm::vec3 value );
    void SetUniform ( std::string name, glm::vec4 value );
    void Update ( Transform&, Camera& );

    GLuint GetProgram ();

    ~Shader ();

private:

    static const unsigned int NUM_SHADERS = 2;
    GLuint m_program;
    GLuint m_shaders [NUM_SHADERS];
};

#endif


code:
/*
 * Writed by Alexey Matveev
 * Original tutorial:
 * https://ravesli.com/urok-6-tekstury-v-opengl/
 */
#include <render/output/texture.h>

#define STB_IMAGE_IMPLEMENTATION
#include <app/modules/thirdParty/stb_image.h>

#include <GLES3/gl3.h>
#include <cassert>
#include <iostream>

Texture::Texture ( const std::string &filename, ATextureFilterType filterType ) {

    unsigned char* data = stbi_load ( filename.c_str (), &width, &height, &nrChannels, 0 );

    if ( data == NULL ) {
        std::cerr << "Texture loading failed: " << filename << std::endl;
    }

    glGenTextures ( 1, &texture ); //arg: count, object of type unsigned int
    glBindTexture ( GL_TEXTURE_2D, texture ); //using current texture

    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    if ( filterType == ATexFilter_Linear ) {
        glTexParameterf ( GL_TEXTURE_2D,  GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameterf ( GL_TEXTURE_2D,  GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    } else if ( filterType == ATexFilter_Near ) {
        glTexParameterf ( GL_TEXTURE_2D,  GL_TEXTURE_MIN_FILTER, GL_NEAREST );
        glTexParameterf ( GL_TEXTURE_2D,  GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    }

    glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data );
    glGenerateMipmap ( GL_TEXTURE_2D );

    stbi_image_free ( data );
}

void Texture::Bind () {

    glBindTexture ( GL_TEXTURE_2D, texture );
}

Texture::~Texture () {
    glDeleteTextures ( 1, &texture );
}


code:
#ifndef TEXTURE_H
#define TEXTURE_H

#include <string>

enum ATextureFilterType {
    ATexFilter_Linear, ATexFilter_Near
};

class Texture {
public:
    Texture ( const std::string &filename, ATextureFilterType );
    void Bind ();
    ~Texture ();
private:
    unsigned int texture;
    int width, height, nrChannels;
};

#endif


code:
/*
 * written by Alexey Matveev according to the lessons
 * https://vulkan-tutorial.com/
*/

#include <render/output/vkrender.h>
#include <render/output/window.h>
#include <vulkan/vulkan.h>
#include <app/Application.h>
#include <app/modules/logger.h>
#include <cstring> //for strcmp()
#include <iostream>

using namespace std;

bool isDeviceSuitable(VkPhysicalDevice device);

void vkrender::mainLoop() {

    while ( !window -> isClosed () ) {

        window -> Update ();
    }
}

void vkrender::initilization( Application& applicationRef, Window* window ) {
    app = &applicationRef;
    this -> window = window;

    VkInstanceCreateInfo InstanceInfo = {};
    VkApplicationInfo applicationInfo = {};

    applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    applicationInfo.pApplicationName = (*app).appName.c_str();
    applicationInfo.applicationVersion = 1;
    applicationInfo.pEngineName = "AME";
    applicationInfo.engineVersion = VK_MAKE_VERSION ( (*app).ameVersionMajor, (*app).ameVersionMinor,
                                                      app -> ameversionCertificate );
    applicationInfo.apiVersion = VK_API_VERSION_1_0;

    InstanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    InstanceInfo.pApplicationInfo = &applicationInfo;

    uint32_t glfwExtensionCount = 0;
    const char** glfwExtensions;

    glfwExtensions = glfwGetRequiredInstanceExtensions ( &glfwExtensionCount );

    InstanceInfo.enabledExtensionCount = glfwExtensionCount;
    InstanceInfo.ppEnabledExtensionNames = glfwExtensions;

    if ( vkCreateInstance( &InstanceInfo, nullptr, &this->instance ) == VK_SUCCESS ) {
        LOG_DEBUG("Vulkan is ready!");
    } else {
        LOG_DEBUG("Error!");
    }

    uint32_t extensionCount = 0;
    vkEnumerateInstanceExtensionProperties ( nullptr, &extensionCount, nullptr );
    std::vector < VkExtensionProperties > extensions ( extensionCount );

    vkEnumerateInstanceExtensionProperties ( nullptr, &extensionCount, extensions.data () );

    LOG_DEBUG ("available extensions:");
    for (const auto& extension : extensions) {
        LOG_DEBUG ( extension.extensionName );
    }

    uint32_t deviceCount = 0;
    vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

    this->devices.resize ( deviceCount );
    vkEnumeratePhysicalDevices ( this->instance, &deviceCount, this->devices.data () );

    if ( deviceCount == 0 ) {
        LOG_DEBUG ( "failed to find GPUs with Vulkan support!" );
    }

    for (const auto& device : this->devices) {

        if ( isDeviceSuitable ( device ) ) {
            physicalDevice = device;
            break;
        }
    }

    if ( physicalDevice == VK_NULL_HANDLE ) {

        LOG_DEBUG ( "failed to find a suitable GPU!" );
    }

    LOG_DEBUG ( "Main loop" );
    mainLoop ();
}

bool isDeviceSuitable ( VkPhysicalDevice device ) {

    VkPhysicalDeviceProperties deviceProperties;
    VkPhysicalDeviceFeatures deviceFeatures;

    vkGetPhysicalDeviceProperties(device, &deviceProperties);
    vkGetPhysicalDeviceFeatures(device, &deviceFeatures);

    return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
        deviceFeatures.geometryShader;
}


code:
#ifndef VKRENDER_H
#define VKRENDER_H

//It's for vulkan window surface
#ifdef __linux__
#define VK_USE_PLATFORM_XCB_KHR
#elif _WIN32
#define VK_USE_PLATFORM_WIN32_KHR
#endif

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <vulkan/vulkan.h>
#include <vector>
#include <string>

#include <app/Application.h>
#include <render/output/window.h>

class vkrender {
public:
    void initilization ( Application&, Window* );

private:
    Application *app;
    Window* window;
    VkInstance instance;
    VkPhysicalDevice physicalDevice;
    std::vector < VkPhysicalDevice > devices;

    void mainLoop ();
};

#endif // VKRENDER_H


code:
#include <render/output/window.h>
#include <app/Application.h>
#include <app/modules/Ainput.h>

#include <GLFW/glfw3.h>
#include <GLES3/gl3.h>

Application *g_app;
Ainput *input;

void keyCallback ( GLFWwindow*, int, int, int, int );
void cursorKeyCallback ( GLFWwindow*, int, int, int );
void cursorPositionCallback ( GLFWwindow*, double, double );
void resizeCallback ( GLFWwindow*, int, int );
void scrollCallback ( GLFWwindow*, double, double );

void initInputDevices(Application* app);

Window::Window ( Application *appPtr ) {

    app = appPtr;
    g_app = appPtr;

    glfwInit ();
    if ( app -> settings.MSAA > 1 ) {
        glfwWindowHint( GLFW_SAMPLES, app -> settings.MSAA );
    }
    if ( !app -> settings.windowResizeble ) {
        glfwWindowHint ( GLFW_RESIZABLE, false );
    }
    if ( app -> settings.textBlending ) {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    if ( !app -> settings.fullscreen ) {
        window = glfwCreateWindow ( app -> settings.windowWidth, app -> settings.windowHeight,
                                    app -> settings.windowName.c_str(), nullptr, nullptr);
    } else {
        window = glfwCreateWindow(glfwGetVideoMode(glfwGetPrimaryMonitor())->width,
                                            glfwGetVideoMode(glfwGetPrimaryMonitor())->height,
                                            app -> settings.windowName.c_str (),
                                            glfwGetPrimaryMonitor(), nullptr);
    }

    glfwMakeContextCurrent ( window );

    glfwSetKeyCallback ( window, keyCallback );
    glfwSetMouseButtonCallback ( window, cursorKeyCallback );
    glfwSetCursorPosCallback ( window, cursorPositionCallback );
    glfwSetWindowSizeCallback ( window, resizeCallback );
    glfwSetScrollCallback ( window, scrollCallback );

    glEnable ( GL_DEPTH_TEST );
    glEnable ( GL_CULL_FACE );
    glCullFace ( GL_BACK );

    input = &( app -> input );

    initInputDevices ( app );
}

bool Window::isClosed () {

    return glfwWindowShouldClose ( window );
}

void Window::Clear ( float R, float G, float B, float A ) {

    glClearColor ( R, G, B, A );
}

void Window::Update () {

    glfwSwapBuffers ( window );
}

Window::~Window () {

    glfwDestroyWindow ( window );
    glfwTerminate ();
}

void keyCallback ( GLFWwindow* window, int key, int scancode, int action, int mods ) {

    input -> keyboard.key = key;

    if ( action == GLFW_PRESS ) {
        input -> keyboard.action = PRESSED;
    } else if ( action == GLFW_REPEAT ) {
        input -> keyboard.action = CLICKED;
    } else if ( action == GLFW_RELEASE ) {
        input -> keyboard.action = UNPRESSED;
    }

    g_app -> keyboardCallback ();
}

void cursorKeyCallback ( GLFWwindow* window, int button, int action, int mods ) {

    if ( button == GLFW_MOUSE_BUTTON_LEFT ) {
        input -> mouse.key = MOUSE_LEFT_BUTTON;
    } else if ( button == GLFW_MOUSE_BUTTON_MIDDLE ) {
        input -> mouse.key = MOUSE_MIDDLE_BUTTON;
    } else if ( button == GLFW_MOUSE_BUTTON_RIGHT ) {
        input -> mouse.key = MOUSE_RIGHT_BUTTON;
    }

    if ( action == GLFW_PRESS ) {
        input -> mouse.action = PRESSED;
    } else if ( action == GLFW_REPEAT ) {
        input -> mouse.action = CLICKED;
    } else if ( action == GLFW_RELEASE ) {
        input -> mouse.action = UNPRESSED;
    }
}

void cursorPositionCallback ( GLFWwindow* window, double xpos, double ypos ) {

    //вычисляем разницу
    input -> mouse.offsetX = xpos - input -> mouse.lastX;
    input -> mouse.offsetY = -( ypos - input -> mouse.lastY );

    //фиксируем последнюю позицию
    input -> mouse.lastX = input -> mouse.posX;
    input -> mouse.lastY = input -> mouse.posY;

    //получаем новую позицию
    input -> mouse.posX = xpos;
    input -> mouse.posY = ypos;

    //умножаем разницу на чувствительность мыши
    input -> mouse.offsetX *= input -> mouse.sensitivity;
    input -> mouse.offsetY *= input -> mouse.sensitivity;

    g_app -> mousePositionCallback ();

}

void resizeCallback ( GLFWwindow* window, int width, int height ) {

    glViewport ( 0, 0, width, height );
}

void scrollCallback ( GLFWwindow* window, double offsetX, double offsetY ) {
    //
}

void initInputDevices ( Application* app ) {

    input -> mouse.lastX = app -> settings.windowWidth / 2;
    input -> mouse.lastY = app -> settings.windowHeight / 2;
}

void Window::grabCursor ( bool value ) {

    if ( value ) {
        glfwSetInputMode ( this -> window, GLFW_CURSOR, GLFW_CURSOR_DISABLED );
    } else {
        glfwSetInputMode ( this -> window, GLFW_CURSOR, GLFW_CURSOR_NORMAL );
    }
}


code:
#ifndef WINDOW_H
#define WINDOW_H

#include <GLFW/glfw3.h>
#include <string>

#include <app/Application.h>

class Window {
public:
    Window ( Application* );
    bool isClosed ();
    void Clear ( float, float, float, float );
    void Update ();
    void grabCursor ( bool );
    ~Window ();
private:
    GLFWwindow* window;
    Application* app;
};

#endif


code:
if [ -d build/ ]; then
    rm -r build
fi


code:
CC=g++

CCTARGET=./simpleameapp

CCINCLUDE=-I../ame/source -I/usr/include/freetype2
CCAMELINKS=-lvulkan -lpthread -lglfw -lGL -lfreetype -lopenal -lalut -ldl
CCAMELINK=../build/*.o

CCVERSION= -std=c++17

CCSRC= \
	main.cpp \

all:
	$(CC) $(CCVERSION) $(CCAMELINK) $(CCSRC) -o $(CCTARGET) $(CCINCLUDE) $(CCAMELINKS)

link:
	@ln -s ../ame/source/render/output/GLSL res

path: simpleAMEapp/Makefile


code:
#include <iostream>
#include <thread>
#include <vector>
#include <cmath>
#include <glm/glm.hpp>

#include <ame.h>
#include <render/output/shader.h>

using namespace std;

Object monkey;
Object stuff;
threadControl coreCtrl;
Application application;
Asound* sound = nullptr;
Window* window = nullptr;
OGLRender* render = nullptr;
Shader* shader = nullptr;
Camera* camera = nullptr;
Texture* brickTexture = nullptr;
Texture* rgLogoTexture = nullptr;
Text* text = nullptr;

bool wasd [4];

unsigned int fps = 0;

void calcFPS ( ) {
    while ( application.running ) {
        application.time.wait ( 1000 );
        cout << "FPS:\t" << fps << endl;
        fps = 0;
    }
}

void playAudio ( ) {
    sound -> play ();
}

void mousePositionUpdate () {

    camera -> setCameraTarget ( &application.input.mouse );
}

void keyboardKeyUpdate () {

    char lastKey = application.input.keyboard.key;
    Action lastAction = application.input.keyboard.action;

    if ( lastKey == 'W' && lastAction != UNPRESSED ) {

        wasd [0] = true;

    } else if ( lastKey == 'W' && lastAction == UNPRESSED ) {

        wasd [0] = false;
    }

    if ( lastKey == 'A' && lastAction != UNPRESSED ) {

        wasd [1] = true;

    } else if ( lastKey == 'A' && lastAction == UNPRESSED ) {

        wasd [1] = false;

    }

    if ( lastKey == 'S' && lastAction != UNPRESSED ) {

        wasd [2] = true;

    } else if ( lastKey == 'S' && lastAction == UNPRESSED ) {

        wasd [2] = false;
    }

    if ( lastKey == 'D' && lastAction != UNPRESSED ) {

        wasd [3] = true;

    } else if ( lastKey == 'D' && lastAction == UNPRESSED ) {

        wasd [3] = false;
    }

    if ( wasd [0] ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x,
                                            camera -> getPosition ().y,
                                            camera -> getPosition ().z + 0.2) );
    }
    if ( wasd [1] ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x + 0.2,
                                            camera -> getPosition ().y,
                                            camera -> getPosition().z ) );
    }
    if ( wasd [2] ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x,
                                            camera -> getPosition ().y,
                                            camera -> getPosition().z - 0.2 ) );
    }
    if ( wasd [3] ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x - 0.2,
                                            camera -> getPosition ().y,
                                            camera -> getPosition().z ) );
    }

    if ( application.input.keyboard.key == 'E' && application.input.keyboard.action != UNPRESSED ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x,
                                            camera -> getPosition ().y + 0.2,
                                            camera -> getPosition().z ) );

    }
    if ( application.input.keyboard.key == 'Q' && application.input.keyboard.action != UNPRESSED ) {

        camera -> setPosition ( glm::vec3 ( camera -> getPosition ().x,
                                            camera -> getPosition ().y - 0.2,
                                            camera -> getPosition().z ) );

    }

    if ( application.input.keyboard.key == 'L' ) {

        shader = new Shader ( "./res/basicShader" );
    }

    if ( application.input.keyboard.key == GLFW_KEY_ESCAPE ) {
        application.running = false;
    }
}

void Update ( ) {

    camera -> applyChanges ();

//    camera -> setFieldOfView ( ( application.input.mouse.posY + application.settings.windowHeight ) / 100);

    shader -> Bind ();
    brickTexture -> Bind ();
    shader -> Update ( monkey.transform, *camera );
    shader -> Update ( stuff.transform, *camera );

    monkey.transform.rotate ( glm::vec3 ( 0.0,
                                                 0.1,
                                                 0.0 ) );

    monkey.mesh -> Draw ();

    rgLogoTexture -> Bind();

    stuff.mesh -> Draw ();

    //text->Print();

    fps++;
}

int main ( )
{
    application.appName = "AMEP";
    application.companyName = "assblast";
    application.update = Update;
    application.mousePositionCallback = mousePositionUpdate;
    application.keyboardCallback = keyboardKeyUpdate;
    application.openGLTools.OpenGLContext = OGLC_GLFW;

    application.settings.fullscreen = false;
    application.settings.windowName = "AREP";
    application.settings.windowWidth = 960;
    application.settings.windowHeight = 540;
    application.settings.windowMonitor = 0;
    application.settings.windowResizeble = false;
    application.settings.MSAA = 8;

    application.input.mouse.sensitivity = 0.05;

    window = new Window ( &application );
    render = new OGLRender ( &application, window );
    shader = new Shader ( "./res/basicShader" );

    camera = new Camera ( glm::vec3 ( 0.0, 0.0, -5.0 ), 70.0,
                          18/9,
                          0.01, 100.0
                        );

    brickTexture = new Texture ( "./bricks.jpg", ATexFilter_Linear );
    rgLogoTexture = new Texture ( "./RGLogo.jpg", ATexFilter_Linear );

    window -> grabCursor ( true );

    Listener listener;
    Source source;

    listener.attributes.position [0] = 0.0;
    listener.attributes.position [1] = 0.0;
    listener.attributes.position [2] = 1.0;

    listener.attributes.velocity [0] = 0.0;
    listener.attributes.velocity [1] = 0.0;
    listener.attributes.velocity [2] = 0.0;

    listener.attributes.orientation [0] = 0.0;
    listener.attributes.orientation [1] = 0.0;
    listener.attributes.orientation [2] = 1.0;

    listener.attributes.orientation [3] = 0.0;
    listener.attributes.orientation [4] = 1.0;
    listener.attributes.orientation [5] = 0.0;

    source.attributes.position [0] = 0.0;
    source.attributes.position [1] = 0.0;
    source.attributes.position [2] = 0.0;

    source.attributes.velocity [0] = 0.0;
    source.attributes.velocity [1] = 0.0;
    source.attributes.velocity [2] = 0.0;

    sound = new Asound ( "sound.wav", source, listener );

    string txt = "QWERTYU";
    /*text = new Text ( txt, 2.0f, glm::vec2 ( 25.0f, 25.0f ), glm::vec3 ( 0.5, 0.8f, 0.2f ),
                      application.settings.windowWidth, application.settings.windowHeight );*/

    monkey.mesh = new Mesh ( "./monkey.obj" );
    stuff.mesh = new Mesh ( "./stuff.obj" );

    coreCtrl.threads.resize ( 1 );
    coreCtrl.threads [0] = new std::thread ( calcFPS );
    coreCtrl.threads [1] = new std::thread ( playAudio );

    render -> joinToMainCycle ();

    coreCtrl.threads [0] -> detach ();

    return 0;
}


code:
//以下全部出自网络和大佬资源，如有冒犯请联系删除。QQ:314511788 [所有内容仅供学习使用，请勿用于违法用途]
//本接口无公众号、无盈利、无引流、免费分享给小白使用，请勿轻信他人，谨防上当受骗。
{
  "spider": "./jar/Yoursmile.jar;md5;1545ef72896b2fa34dec2f79a8e625ce",
  "wallpaper": "https://tuapi.eees.cc/api.php?category=fengjing&type=302",
  "sites": [
  {
     "key": "csp_短剧香",
     "name": "🥝网香短剧",
     "type": 3,
     "api": "csp_XYQHiker",
     "jar": "./jar/xyq910.jar",
     "searchable": 1,
     "quickSearch": 1,
     "filterable": 1,
     "ext": "https://jihulab.com/wdyzy/hy/-/raw/main/json/dj.json"
    },
    {
      "key": "横版影院",
      "name": "🍓横版短剧",
      "type": 1,
      "api": "https://cj.lzcaiji.com/api.php/provide/vod/from/liangzi/?ac=list",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "categories": [ "短剧" ]
    },
    {
        "key": "yqkan_pen",
        "name": "❤短剧一",
        "type": 3,
        "api": "csp_YQKan",
        "searchable": 1,
        "quickSearch": 1,
        "filterable": 0,
        "jar":"./jar/OpenSpider.jar"
    },
    {
       "key":"咕咕咕",
       "name":"💛 短剧二",
       "type":3,
       "api":"csp_AppYsV2",
       "searchable":1,
       "quickSearch":1,
       "filterable":1,
       "ext":"https://www.kuin.one/api.php/app/"
    },
    {
       "key":"姐姐",
       "name":"💙短剧四",
       "type":3,
       "api":"csp_AppYsV2",
       "searchable":1,
       "quickSearch":1,
       "filterable":1,
       "ext":"http://dytt996.com/api.php/app/"
    },
   {
      "key": "csp_XBPQ_vstv",
      "name": "💖短剧七",
      "type": 3,
      "api": "csp_XBPQ",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": {
      "分类url": "https://www.ytshengde.com/sanyisw/{cateId}-{area}-------{catePg}---{year}.html",
      "分类": "短剧$5#电视剧$2#电影$1#动漫$4#综艺$3"}
    },
    {
      "key":"csp_XBPQ_miniju",
      "name":"💝短剧八",
      "type":3,
      "api":"csp_XBPQ",
      "searchable":1,
      "quickSearch":1,
      "filterable":1,
      "ext":{"分类url":"https://mimiju.com/vodshow/{cateId}--{by}------{catePg}---.html",
      "分类":"短剧$20#电影$22#电视剧$21#动漫$23#综艺$24"}
   },
   {
      "key": "csp_XBPQ_aoaotv",
      "name": "💗短剧九",
      "type": 3,
      "api": "csp_XBPQ",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": {
        "分类url": "https://aoao.tv/vodshow/{cateId}--------{catePg}---.html",
        "分类": "短剧$20#电视剧$21#电影$22#动漫$23#综艺$24"}
    }
  ],
"parses": [
    { "name": "解析轮询", "type": 3, "url": "Demo"},
    { "name": "嗅探轮询", "type": 3, "url": "Web"},
    { "name": "json轮询", "type": 2, "url": "Sequence"},
    { "name": "银河解析", "type": 1, "url": "https://jxjson.cf/json.php?url="},
    { "name": "左岸解析", "type": 1, "url": "http://pandown.pro/app/lvdou.php?url="},
    { "name": "右岸解析", "type": 1, "url": "http://pandown.pro/app/kkdy.php?url="},
    { "name": "云端解析", "type": 1, "url": "https://api.tyun77.cn/api.php/provide/parseDicturl?url="},
    { "name": "爱酷解析", "type": 1, "url": "http://cache.json.icu/1804857380.php?url="},
    { "name": "爱酷嗅探", "type": 0, "url": "https://jx.zhanlangbu.com/?url="},
    { "name": "银河嗅探", "type": 0, "url": "https://jx.jsonplayer.com/player/?url="},
    { "name": "4433嗅探", "url": "https://jx.bozrc.com:4433/player/?url=","showType": 1"},
    { "name": "777嗅探","type": 0, "url":"https://jx.777jiexi.com/player/?url="},
    { "name": "云嗅探","type": 0,"url": "https://jx.yparse.com/index.php?url="}
    ],
  "lives": [
    {"name": "live","type": 0,
      "url": "https://gitcode.net/wdytcl/hy/-/raw/master/live.txt",
      "epg": "http://epg.112114.xyz/?ch={name}&date={date}",
      "logo": "https://epg.112114.xyz/logo/{name}.png"}],
  "doh": [
    {"name": "Google", "url": "https://dns.google/dns-query", "ips": ["8.8.4.4", "8.8.8.8"]},
    {"name": "Cloudflare", "url": "https://cloudflare-dns.com/dns-query","ips":["1.1.1.1","1.0.0.1","2606:4700:4700::1111","2606:4700:4700::1001"]},
    {"name": "AdGuard", "url": "https://dns.adguard.com/dns-query","ips": [ "94.140.14.140","94.140.14.141"]},
    {"name": "DNSWatch", "url": "https://resolver2.dns.watch/dns-query","ips": [ "84.200.69.80","84.200.70.40"]},
    {"name": "Quad9","url": "https://dns.quad9.net/dns-quer","ips": [ "9.9.9.9","149.112.112.112"]}],
 "rules":[
{"name":"量子","hosts":["vip.lz","hd.lz"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.433333,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"非凡","hosts":["vip.ffzy","hd.ffzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.666667,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"暴风","hosts":["bfzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:3,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"火山","hosts":["huoshan.com"],"regex":["item_id="]},
{"name":"抖音","hosts":["douyin.com"],"regex":["is_play_url="]},
{"name":"磁力","hosts":["magnet"],"regex":["最 新","直 播","更 新"]}],
 "flags":
 ["youku","优酷","优酷视频","qq","腾讯","腾讯视频","iqiyi","qiyi","奇艺","爱奇艺", "m1905","xigua","letv","leshi","乐视","sohu","搜狐","搜狐视频", "tudou","pptv","mgtv","芒果","imgo", "芒果TV", "bilibili","哔 哩"],
  "ijk":[
{"group":"软解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"0"},
{"category":4,"name":"mediacodec-auto-rotate","value":"0"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"0"},
{"category":4,"name":"mediacodec-hevc","value":"0"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]},
{"group":"硬解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"1"},
{"category":4,"name":"mediacodec-auto-rotate","value":"1"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"1"},
{"category":4,"name":"mediacodec-hevc","value":"1"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]}],
"ads":[
"mimg.0c1q0l.cn","www.googletagmanager.com","www.google-analytics.com","mc.usihnbcq.cn",
"mg.g1mm3d.cn","mscs.svaeuzh.cn","cnzz.hhttm.top","tp.vinuxhome.com","cnzz.mmstat.com",
"www.baihuillq.com","s23.cnzz.com","z3.cnzz.com","c.cnzz.com","stj.v1vo.top","z12.cnzz.com",
"img.mosflower.cn","tips.gamevvip.com","ehwe.yhdtns.com","xdn.cqqc3.com","www.jixunkyy.cn",
"sp.chemacid.cn","hm.baidu.com","s9.cnzz.com","z6.cnzz.com","um.cavuc.com","mav.mavuz.com",
"wofwk.aoidf3.com","z5.cnzz.com","xc.hubeijieshikj.cn","tj.tianwenhu.com","xg.gars57.cn","k.jinxiuzhilv.com",
"cdn.bootcss.com","ppl.xunzhuo123.com","xomk.jiangjunmh.top","img.xunzhuo123.com",
"z1.cnzz.com","s13.cnzz.com","xg.huataisangao.cn","z7.cnzz.com","xg.huataisangao.cn",
"z2.cnzz.com","s96.cnzz.com","q11.cnzz.com","thy.dacedsfa.cn","xg.whsbpw.cn","s19.cnzz.com",
"z8.cnzz.com","s4.cnzz.com","f5w.as12df.top","ae01.alicdn.com","www.92424.cn",
"k.wudejia.com","vivovip.mmszxc.top","qiu.xixiqiu.com","cdnjs.hnfenxun.com","cms.qdwght.com"]
}


code:
//以下全部出自网络和大佬资源，如有冒犯请联系删除。QQ:314511788 [所有内容仅供学习使用，请勿用于违法用途]
//本接口无公众号、无盈利、无引流、免费分享给小白使用，请勿轻信他人，谨防上当受骗。
 {
  "spider": "./jar/Yoursmile.jar;md5;1545ef72896b2fa34dec2f79a8e625ce",
  "wallpaper": "https://tuapi.eees.cc/api.php?category=fengjing&type=302",
  "sites": [
    {
      "key": "js豆瓣",
      "name": "🔍豆瓣推荐",
      "type": 3,
      "api": "./js/drpy.min.js",
      "ext": "./json/豆瓣.js"
    },
    {
      "key": "废物影视",
      "name": "银河聚合",
      "searchable": 1,
      "quickSearch": 1,
      "type":1,
      "api":"http://playersll.gaoxin155.com.cn/api.php/provide/vod/",
      "filterable": 1,
      "categories": ["国产剧","港台剧","欧美剧","日韩剧","综艺","科幻片","奇幻片","喜剧片","爱情片",
                     "惊悚片","犯罪片","冒险片","动作片","战争片","悬疑片","剧情片","记录片","动漫"]
    },
    {
      "key": "csp_WoGG2",
      "name": "玩偶云盘T4",
      "type": 4,
      "api": "http://home.jundie.top:9520/spider/csp_Wogg?sort=原画,蓝光,超清,高清       &token=0068144bf4d24f3284819c15f3a49482",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1
    },
    {
      "key": "drpy_js_奇珍异兽",
      "name": "奇艺官源",
      "type": 3,
      "searchable": 1,
      "quickSearch": 1,
      "api": "./js/drpy.min.js",
      "ext": "./json/奇异.js"
    },
    {
      "key": "mtv_搜狗视频",
      "name": "搜狗视频",
      "type": 3,
      "api": "./js/drpy.min.js",
      "searchable": 2,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/菜狗.js"
    },
    {
      "key": "Qtv",
      "name": "🐧腾讯解析",
      "type": 3,
      "api": "csp_Qtv",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "changeable": 0
    },
    {
      "key": "csp_Czsapp",
      "name": "🏭厂长资源",
      "type": 3,
      "api": "csp_Czsapp",
      "playerType": 2,
      "searchable": 1,
      "quickSearch": 1,
      "ext": "https://www.czzy88.com/",
      "filterable": 1,
      "jar":"./jar/yinhe.jar"
    },
    {
      "key": "PanSou",
      "name": "😽盘搜S",
      "type": 3,
      "api": "csp_PanSou",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "UpYun",
      "name": "☁UP云搜S",
      "type": 3,
      "api": "csp_UpYun",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "YiSo",
      "name": "🆎易搜S",
      "type": 3,
      "api": "csp_YiSo",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "PanSearch",
      "name": "🙀盘搜索S",
      "type": 3,
      "api": "csp_PanSearch",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0
    },
    {
      "key": "csp_SP33",
      "name": "📺360解析",
      "type": 3,
      "api": "csp_SP33",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "changeable": 0
    },
    {
      "key": "Mtv",
      "name": "🍋芒果解析",
      "type": 3,
      "api": "csp_Mtv",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "changeable": 0
    },
    {
      "key": "云播",
      "name": " ☁TVB云播",
      "type": 3,
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "api": "csp_XBPQ",
      "ext": "./json/TVB云播.json"
    },
    {
       "key": "007",
       "name": "♹007影院",
       "type": 3,
       "api": "csp_XBPQ",
       "searchable": 1,
       "quickSearch": 1,
       "filterable": 1,
       "ext": "./json/007影视.json"
    },
    {
      "key": "TV酷影",
      "name": "TV酷影视",
      "type": 3,
      "api": "csp_AppYsV2",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "https://www.tvkuys.xyz/api.php/app/"
    },
    {
      "key": "子子",
      "name": "📹子子影院",
      "type": 3,
      "api": "csp_XBPQ",
      "playerType": "1",
      "searchable": 1,
      "quickSearch": 1,
      "ext": "./json/子子影院.json"
    },
    {
      "key": "XBPQ_voflix",
      "name": "voflix电影网",
      "type": 3,
      "api": "csp_XBPQ",
      "filterable": 1,
      "quickSearch": 1,
      "searchable": 1,
      "ext": "./json/voflix.json"
    },
    {
      "key": "freeok",
      "name": "🍾菲克高清",
      "type": 3,
      "api": "csp_XBPQ",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "./json/菲克高清.json"
    },
    {
      "key": "6080",
      "name": "新视觉影院",
      "type": 3,
      "api": "csp_Xinsj",
      "searchable": 1,
      "quickSearch": 1,
      "changeable": 1,
      "ext": "https://www.6080yy3.com/"
    },
    {
      "key": "秋霞电影",
      "name":"🌈秋霞聚合",
      "type":3,
      "api":"csp_XBPQ",
      "searchable":1,
      "quickSearch":1,
      "filterable":1,
      "ext":"./json/秋霞.json"
    },
    {
      "key": "csp_Zxzj",
      "name": "🏠海外剧场",
      "type": 3,
      "api": "csp_Zxzj",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "https://www.zxzj.pro/"
    },
    {
      "key": "量子",
      "name": "💢量子资源",
      "type": 0,
      "api": "https://cj.lziapi.com/api.php/provide/vod/at/xml/",
      "searchable": 1,
      "changeable": 1,
      "categories": [
           "国产剧","韩国剧","日本剧","台湾剧","香港剧","欧美剧","泰国剧","海外剧",
           "动作片","喜剧片","爱情片","科幻片","剧情片","战争片","记录片",
           "大陆综艺","港台综艺","日韩综艺","欧美综艺"]
    },
    {
      "key": "csp_xml_ck",
      "name": "🎀CK资源",
      "type": 0,
      "api": "https://ckzy.me/api.php/provide/vod/at/xml/",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "categories": [
        "国产剧","欧美剧","日韩剧","港台剧","奇幻片","动作片","喜剧片","爱情片","科幻片",
        "剧情片","战争片","记录片"]
    },
    {
      "key": "csp_Bili",
      "name": "🅱休闲综合",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "./json/bilizh.json"
    },
    {
      "key": "音乐",
      "name": "🎤文艺综合",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/文艺.json"
    },
    {
      "key":"MV_vod",
      "name":"🎸明星MV",
      "type":1,
      "api":"https://mv.wogg.link/mv/vod",
      "searchable":0,
      "quickSearch":0,
      "filterable":1
    },
    {
      "key":"戏曲",
      "name":"🅱戏曲",
      "type":3,
      "api":"csp_Bili",
      "searchable":0,
      "quickSearch":0,
      "filterable":1,
      "ext":"https://agit.ai/Yoursmile7/TVBox/raw/branch/master/sub/Blixq.json"
    },
    {
      "key":"酷奇MV",
      "name":"🎤酷奇MV",
      "type":3,
      "api":"csp_XBPQ",
      "searchable":0,
      "quickSearch":0,
      "filterable":1,
      "ext":{"主页url":"https://www.kuqimv.com",
      "直接播放":"1",
      "短视频":"1",
      "分类":"华语高清$1#日韩精选$2#欧美MV$3#高清现场$4#影视MV$5#夜店视频$6#车模视频$7#热舞视频$8#美女打碟$9",
      "分类url":"https://www.kuqimv.com/play/{cateId}_{catePg}.html;;z","数组":"<li>&&</li>",
      "标题":"title=\"&&\"","副标题":"target=\"play\">&&<","搜索模式":"1",
      "搜索url":"https://www.kuqimv.com/search.php?key={wd}"}
    },
    {
      "key" : "美食",
      "name" : "🍔美食合集",
      "type" : 3,
      "api" : "csp_Bili",
      "searchable" : 0,
      "quickSearch" : 0,
      "filterable" : 1,
      "ext" : "./json/美食.json"
    },
    {
      "key": "健身",
      "name": "养生﹠健身",
      "type": 3,
      "api": "csp_Bili",
      "ext": "./json/健身.json"
    },
    {  "key":"Aid",
       "name":"🚑急救教学",
       "type":3,
       "api":"csp_FirstAid",
       "jar": "./jar/spider.jar",
       "searchable":0,
       "quickSearch":0,
       "filterable":0,
       "changeable":0
    },
    {
      "key": "儿童",
      "name": "🐯儿童乐园",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%84%BF%E7%AB%A5.json"
    },
    {
      "key": "小学",
      "name": "小学课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%84%BF%E7%AB%A5.json"
    },
    {
      "key": "初中",
      "name": "初中课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%88%9D%E4%B8%AD.json"
    },
    {
      "key": "高中",
      "name": "高中课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E9%AB%98%E4%B8%AD.json"
    },
    {
      "key": "外语",
      "name": "外语学习",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%A4%96%E8%AF%AD.json"
    },
    {
      "key": "软件",
      "name": "📚教程﹠讲座A",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext":"./json/%E6%95%99%E7%A8%8B.json"
    },
    {
      "key": "教程",
      "name": "📚教程﹠讲座B",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext":"./json/软件.json"
    },
    {"key":"18","name":"有S标记为搜网盘用，用手机阿里云盘扫码观看","type":0,"api":""}
  ],
"parses": [
    { "name": "解析轮询", "type": 3, "url": "Demo"},
    { "name": "嗅探轮询", "type": 3, "url": "Web"},
    { "name": "json轮询", "type": 2, "url": "Sequence"},
    { "name": "银河解析", "type": 1, "url": "https://jxjson.cf/json.php?url="},
    { "name": "左岸解析", "type": 1, "url": "http://pandown.pro/app/lvdou.php?url="},
    { "name": "右岸解析", "type": 1, "url": "http://pandown.pro/app/kkdy.php?url="},
    { "name": "云端解析", "type": 1, "url": "https://api.tyun77.cn/api.php/provide/parseDicturl?url="},
    { "name": "爱酷解析", "type": 1, "url": "http://cache.json.icu/1804857380.php?url="},
    { "name": "爱酷嗅探", "type": 0, "url": "https://jx.zhanlangbu.com/?url="},
    { "name": "银河嗅探", "type": 0, "url": "https://jx.jsonplayer.com/player/?url="},
    { "name": "4433嗅探", "url": "https://jx.bozrc.com:4433/player/?url=","showType": 1"},
    { "name": "777嗅探","type": 0, "url":"https://jx.777jiexi.com/player/?url="},
    { "name": "云嗅探","type": 0,"url": "https://jx.yparse.com/index.php?url="}
    ],
  "lives": [
    {"name": "live","type": 0,
      "url": "https://gitcode.net/wdytcl/hy/-/raw/master/live.txt",
      "epg": "http://epg.112114.xyz/?ch={name}&date={date}",
      "logo": "https://epg.112114.xyz/logo/{name}.png"}],
  "doh": [
    {"name": "Google", "url": "https://dns.google/dns-query", "ips": ["8.8.4.4", "8.8.8.8"]},
    {"name": "Cloudflare", "url": "https://cloudflare-dns.com/dns-query","ips":["1.1.1.1","1.0.0.1","2606:4700:4700::1111","2606:4700:4700::1001"]},
    {"name": "AdGuard", "url": "https://dns.adguard.com/dns-query","ips": [ "94.140.14.140","94.140.14.141"]},
    {"name": "DNSWatch", "url": "https://resolver2.dns.watch/dns-query","ips": [ "84.200.69.80","84.200.70.40"]},
    {"name": "Quad9","url": "https://dns.quad9.net/dns-quer","ips": [ "9.9.9.9","149.112.112.112"]}],
 "rules":[
{"name":"量子","hosts":["vip.lz","hd.lz"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.433333,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"非凡","hosts":["vip.ffzy","hd.ffzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.666667,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"暴风","hosts":["bfzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:3,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"火山","hosts":["huoshan.com"],"regex":["item_id="]},
{"name":"抖音","hosts":["douyin.com"],"regex":["is_play_url="]},
{"name":"磁力","hosts":["magnet"],"regex":["最 新","直 播","更 新"]}],
 "flags":
 ["youku","优酷","优酷视频","qq","腾讯","腾讯视频","iqiyi","qiyi","奇艺","爱奇艺", "m1905","xigua","letv","leshi","乐视","sohu","搜狐","搜狐视频", "tudou","pptv","mgtv","芒果","imgo", "芒果TV", "bilibili","哔 哩"],
  "ijk":[
{"group":"软解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"0"},
{"category":4,"name":"mediacodec-auto-rotate","value":"0"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"0"},
{"category":4,"name":"mediacodec-hevc","value":"0"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]},
{"group":"硬解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"1"},
{"category":4,"name":"mediacodec-auto-rotate","value":"1"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"1"},
{"category":4,"name":"mediacodec-hevc","value":"1"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]}],
"ads":[
"mimg.0c1q0l.cn","www.googletagmanager.com","www.google-analytics.com","mc.usihnbcq.cn",
"mg.g1mm3d.cn","mscs.svaeuzh.cn","cnzz.hhttm.top","tp.vinuxhome.com","cnzz.mmstat.com",
"www.baihuillq.com","s23.cnzz.com","z3.cnzz.com","c.cnzz.com","stj.v1vo.top","z12.cnzz.com",
"img.mosflower.cn","tips.gamevvip.com","ehwe.yhdtns.com","xdn.cqqc3.com","www.jixunkyy.cn",
"sp.chemacid.cn","hm.baidu.com","s9.cnzz.com","z6.cnzz.com","um.cavuc.com","mav.mavuz.com",
"wofwk.aoidf3.com","z5.cnzz.com","xc.hubeijieshikj.cn","tj.tianwenhu.com","xg.gars57.cn","k.jinxiuzhilv.com",
"cdn.bootcss.com","ppl.xunzhuo123.com","xomk.jiangjunmh.top","img.xunzhuo123.com",
"z1.cnzz.com","s13.cnzz.com","xg.huataisangao.cn","z7.cnzz.com","xg.huataisangao.cn",
"z2.cnzz.com","s96.cnzz.com","q11.cnzz.com","thy.dacedsfa.cn","xg.whsbpw.cn","s19.cnzz.com",
"z8.cnzz.com","s4.cnzz.com","f5w.as12df.top","ae01.alicdn.com","www.92424.cn",
"k.wudejia.com","vivovip.mmszxc.top","qiu.xixiqiu.com","cdnjs.hnfenxun.com","cms.qdwght.com"]
}


code:
//以下全部出自网络和大佬资源，如有冒犯请联系删除。QQ:314511788 [所有内容仅供学习使用，请勿用于违法用途]
//本接口无公众号、无盈利、无引流、免费分享给小白使用，请勿轻信他人，谨防上当受骗。
 {
  "spider": "./jar/Yoursmile.jar;md5;1545ef72896b2fa34dec2f79a8e625ce",
  "wallpaper": "https://tuapi.eees.cc/api.php?category=fengjing&type=302",
  "sites": [
    {
      "key": "js豆瓣",
      "name": "🔍豆瓣推荐",
      "type": 3,
      "api": "./js/drpy.min.js",
      "ext": "./json/豆瓣.js"
    },
    {
      "key": "废物影视",
      "name": "银河聚合",
      "searchable": 1,
      "quickSearch": 1,
      "type":1,
      "api":"http://playersll.gaoxin155.com.cn/api.php/provide/vod/",
      "filterable": 1,
      "categories": ["国产剧","港台剧","欧美剧","日韩剧","综艺","科幻片","奇幻片","喜剧片","爱情片",
                     "惊悚片","犯罪片","冒险片","动作片","战争片","悬疑片","剧情片","记录片","动漫"]
    },
    {
      "key": "csp_WoGG2",
      "name": "玩偶云盘T4",
      "type": 4,
      "api": "http://home.jundie.top:9520/spider/csp_Wogg?sort=原画,蓝光,超清,高清       &token=0068144bf4d24f3284819c15f3a49482",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1
    },
    {
      "key": "PanSou",
      "name": "😽盘搜S",
      "type": 3,
      "api": "csp_PanSou",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "UpYun",
      "name": "☁UP云搜S",
      "type": 3,
      "api": "csp_UpYun",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "YiSo",
      "name": "🆎易搜S",
      "type": 3,
      "api": "csp_YiSo",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0,
      "changeable": 0
    },
    {
      "key": "PanSearch",
      "name": "🙀盘搜索S",
      "type": 3,
      "api": "csp_PanSearch",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0
    },
    {
      "key": "qqtv",
      "name": "丽丽影视",
      "type": 3,
      "api": "csp_AppYsV2",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "https://www.qqtv.vip/icciu_api.php/v1.vod"
    },
    {
        "key": "彩虹",
	"name": "彩虹影视",
	"type": 3,
	"api": "csp_AppYsV2",
	"playerType": 1,
	"searchable": 1,
	"quickSearch": 1,
	"changeable": 1,
	"ext": "http://ys.qtw.asia/lvdou_api.php/v1.vod"
    },
    {
	"key": "享看",
	"name": "想看影视",
	"type": 1,
	"searchable": 1,
	"quickSearch": 1,
	"filterable": 1,
	"api": "https://xkanzy5.com/api.php/provide/vod/",
	"playUrl": "json:http://shixiong.alwaysdata.net/m3u8/xk.php?url=",
	"categories": [
	"国产剧",
	"日韩剧",
	"港台剧",
	"欧美剧",
	"动作片",
	"战争片",
	"喜剧片",
	"大陆综艺",
	"国产动漫"]
    },
    {
	"key": "zy_新浪资源",
	"name": "新浪资源",
	"type": 0,
	"api": "https://api.xinlangapi.com/xinlangapi.php/provide/vod/from/xlm3u8/at/xml/",
	"searchable": 1,
	"quickSearch": 1,
	"filterable": 0,
	"categories": [
	"动作片",
	"爱情片",
	"科幻片",
	"战争片",
	"剧情片",
	"恐怖片",
	"喜剧片",
	"纪录片",
	"大陆剧",
	"港澳剧",
	"台湾剧",
	"欧美剧",
	"动漫电影",
	"动漫",
	"综艺",,
	"韩剧",
	"日剧",
	"泰剧",
	"体育"]
   },
    {
	"key": "49zy",
	"name": "49影视",
	"type": 1,
	"api": "https://49zyw.com/api.php/provide/vod/?ac=list",
	"searchable": 1,
	"quickSearch": 1,
	"filterable": 1,
	"categories": [
	"国产剧",
	"纪录片",
	"欧美剧",
	"香港剧",
	"动作片",
	"爱情片",
	"科幻片",
	"恐怖片",
	"剧情片",
	"战争片",
	"喜剧片",
	"动画片",
	"犯罪片",
	"韩国剧",
	"动漫",
	"电影",
	"大陆综艺",
	"港台综艺",
	"日韩综艺",
	"欧美综艺",
	"台湾剧",
	"国产动漫",
	"日本动漫",
	"欧美动漫",
	"泰国剧",
	"日剧",
	"电影解说",
	"奇幻片",
	"灾难片",
	"悬疑片",
	"其他片",
	"体育赛事",
	"海外剧"]
    },
    {
	"key": "豪华资源",
	"name": "豪华资源",
	"type": 1,
	"api": "https://hhzyapi.com/api.php/provide/vod/from/hhm3u8/at/json",
	"searchable": 1,
	"quickSearch": 1,
	"categories": [
	"内地剧",
	"香港剧",
	"欧美剧",
	"韩剧",
	"日剧",
	"马泰剧",
	"台湾剧",
	"动画片",
	"中国动漫",
	"日本动漫",
	"欧美动漫",
	"剧情片",
	"战争片",
	"动作片",
	"科幻片",
	"记录片",
	"爱情片",
	"喜剧片",
	"灾难片",
	"悬疑片",
	"犯罪片",
	"大陆综艺",
	"日韩综艺",
	"港台综艺",
	"欧美综艺"]
    },
    {
	"key": "爱坤",
	"name": "爱坤影视",
	"type": 1,
	"searchable": 1,
	"quickSearch": 1,
	"filterable": 1,
	"api": "https://ikunzyapi.com/api.php/provide/vod",
	"categories": [
	"国产剧",
	"香港剧",
	"台湾剧",
	"韩国剧",
	"日本剧",
	"欧美剧",
	"海外剧",
	"泰国剧",
	"动画片",
	"动作片",
	"喜剧片",
	"科幻片",
	"恐怖片",
	"爱情片",
	"剧情片",
	"战争片",
	"古装片",
	"历史片",
	"家庭片",
	"记录片",
	"国产动漫",
	"日本动漫",
	"欧美动漫",
	"大陆综艺",
	"港台综艺",
	"日韩综艺",
	"欧美综艺"]
    },
    {
	"key": "csp_非凡资源",
	"name": "非凡采集",
	"type": 1,
	"api": "http://cj.ffzyapi.com/api.php/provide/vod/from/ffm3u8",
	"playUrl": "json:http://118.25.184.129:9668/?url=",
	"quickSearch": 1,
	"filterable": 1,
	"categories": [
	"动作片",
	"喜剧片",
	"科幻片",
	"恐怖片",
	"爱情片",
	"剧情片",
	"战争片",
	"记录片",
	"国产剧",
	"欧美剧",
	"香港剧",
	"韩国剧",
	"台湾剧",
	"日本剧",
	"海外剧",
	"泰国剧",
	"国产动漫",
	"日韩动漫",
	"欧美动漫",
	"港台动漫",
	"海外动漫",
	"大陆综艺",
	"港台综艺",
	"日韩综艺",
	"欧美综艺"]
    },
    {
      "key": "csp_DiDuan",
      "name": "📺低端影视",
      "type": 3,
      "api": "csp_Ddrk",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 0
    },
    {
      "key": "csp_Bili",
      "name": "🅱休闲综合",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 1,
      "quickSearch": 1,
      "filterable": 1,
      "ext": "./json/bilizh.json"
    },
    {
      "key": "音乐",
      "name": "🎤文艺综合",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/文艺.json"
    },
    {
      "key":"MV_vod",
      "name":"🎸明星MV",
      "type":1,
      "api":"https://mv.wogg.link/mv/vod",
      "searchable":0,
      "quickSearch":0,
      "filterable":1
    },
    {
      "key":"戏曲",
      "name":"🅱戏曲",
      "type":3,
      "api":"csp_Bili",
      "searchable":0,
      "quickSearch":0,
      "filterable":1,
      "ext":"https://agit.ai/Yoursmile7/TVBox/raw/branch/master/sub/Blixq.json"
    },
    {
      "key":"酷奇MV",
      "name":"🎤酷奇MV",
      "type":3,
      "api":"csp_XBPQ",
      "searchable":0,
      "quickSearch":0,
      "filterable":1,
      "ext":{"主页url":"https://www.kuqimv.com",
      "直接播放":"1",
      "短视频":"1",
      "分类":"华语高清$1#日韩精选$2#欧美MV$3#高清现场$4#影视MV$5#夜店视频$6#车模视频$7#热舞视频$8#美女打碟$9",
      "分类url":"https://www.kuqimv.com/play/{cateId}_{catePg}.html;;z","数组":"<li>&&</li>",
      "标题":"title=\"&&\"","副标题":"target=\"play\">&&<","搜索模式":"1",
      "搜索url":"https://www.kuqimv.com/search.php?key={wd}"}
    },
    {
      "key" : "美食",
      "name" : "🍔美食合集",
      "type" : 3,
      "api" : "csp_Bili",
      "searchable" : 0,
      "quickSearch" : 0,
      "filterable" : 1,
      "ext" : "./json/美食.json"
    },
    {
      "key": "健身",
      "name": "养生﹠健身",
      "type": 3,
      "api": "csp_Bili",
      "ext": "./json/健身.json"
    },
    {  "key":"Aid",
       "name":"🚑急救教学",
       "type":3,
       "api":"csp_FirstAid",
       "jar": "./jar/spider.jar",
       "searchable":0,
       "quickSearch":0,
       "filterable":0,
       "changeable":0
    },
    {
      "key": "儿童",
      "name": "🐯儿童乐园",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%84%BF%E7%AB%A5.json"
    },
    {
      "key": "小学",
      "name": "小学课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%84%BF%E7%AB%A5.json"
    },
    {
      "key": "初中",
      "name": "初中课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%88%9D%E4%B8%AD.json"
    },
    {
      "key": "高中",
      "name": "高中课堂",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E9%AB%98%E4%B8%AD.json"
    },
    {
      "key": "外语",
      "name": "外语学习",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext": "./json/%E5%A4%96%E8%AF%AD.json"
    },
    {
      "key": "软件",
      "name": "📚教程﹠讲座A",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext":"./json/%E6%95%99%E7%A8%8B.json"
    },
    {
      "key": "教程",
      "name": "📚教程﹠讲座B",
      "type": 3,
      "api": "csp_Bili",
      "searchable": 0,
      "quickSearch": 0,
      "filterable": 1,
      "ext":"./json/软件.json"
    },
    {"key":"18","name":"有S标记为搜网盘用，用手机阿里云盘扫码观看","type":0,"api":""}
  ],
"parses": [
    { "name": "解析轮询", "type": 3, "url": "Demo"},
    { "name": "嗅探轮询", "type": 3, "url": "Web"},
    { "name": "json轮询", "type": 2, "url": "Sequence"},
    { "name": "银河解析", "type": 1, "url": "https://jxjson.cf/json.php?url="},
    { "name": "左岸解析", "type": 1, "url": "http://pandown.pro/app/lvdou.php?url="},
    { "name": "右岸解析", "type": 1, "url": "http://pandown.pro/app/kkdy.php?url="},
    { "name": "云端解析", "type": 1, "url": "https://api.tyun77.cn/api.php/provide/parseDicturl?url="},
    { "name": "爱酷解析", "type": 1, "url": "http://cache.json.icu/1804857380.php?url="},
    { "name": "爱酷嗅探", "type": 0, "url": "https://jx.zhanlangbu.com/?url="},
    { "name": "银河嗅探", "type": 0, "url": "https://jx.jsonplayer.com/player/?url="},
    { "name": "4433嗅探", "url": "https://jx.bozrc.com:4433/player/?url=","showType": 1"},
    { "name": "777嗅探","type": 0, "url":"https://jx.777jiexi.com/player/?url="},
    { "name": "云嗅探","type": 0,"url": "https://jx.yparse.com/index.php?url="}
    ],
  "lives": [
    {"name": "live","type": 0,
      "url": "https://gitcode.net/wdytcl/hy/-/raw/master/live.txt",
      "epg": "http://epg.112114.xyz/?ch={name}&date={date}",
      "logo": "https://epg.112114.xyz/logo/{name}.png"}],
  "doh": [
    {"name": "Google", "url": "https://dns.google/dns-query", "ips": ["8.8.4.4", "8.8.8.8"]},
    {"name": "Cloudflare", "url": "https://cloudflare-dns.com/dns-query","ips":["1.1.1.1","1.0.0.1","2606:4700:4700::1111","2606:4700:4700::1001"]},
    {"name": "AdGuard", "url": "https://dns.adguard.com/dns-query","ips": [ "94.140.14.140","94.140.14.141"]},
    {"name": "DNSWatch", "url": "https://resolver2.dns.watch/dns-query","ips": [ "84.200.69.80","84.200.70.40"]},
    {"name": "Quad9","url": "https://dns.quad9.net/dns-quer","ips": [ "9.9.9.9","149.112.112.112"]}],
 "rules":[
{"name":"量子","hosts":["vip.lz","hd.lz"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.433333,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"非凡","hosts":["vip.ffzy","hd.ffzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:6.666667,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"暴风","hosts":["bfzy"],"regex":["#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:3,[\\s\\S]*?#EXT-X-DISCONTINUITY","#EXTINF.*?\\s+.*?1o.*?\\.ts\\s+"]},
{"name":"火山","hosts":["huoshan.com"],"regex":["item_id="]},
{"name":"抖音","hosts":["douyin.com"],"regex":["is_play_url="]},
{"name":"磁力","hosts":["magnet"],"regex":["最 新","直 播","更 新"]}],
 "flags":
 ["youku","优酷","优酷视频","qq","腾讯","腾讯视频","iqiyi","qiyi","奇艺","爱奇艺", "m1905","xigua","letv","leshi","乐视","sohu","搜狐","搜狐视频", "tudou","pptv","mgtv","芒果","imgo", "芒果TV", "bilibili","哔 哩"],
  "ijk":[
{"group":"软解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"0"},
{"category":4,"name":"mediacodec-auto-rotate","value":"0"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"0"},
{"category":4,"name":"mediacodec-hevc","value":"0"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]},
{"group":"硬解码","options":[
{"category":4,"name":"opensles","value":"0"},
{"category":4,"name":"overlay-format","value":"842225234"},
{"category":4,"name":"framedrop","value":"1"},
{"category":4,"name":"soundtouch","value":"1"},
{"category":4,"name":"start-on-prepared","value":"1"},
{"category":1,"name":"http-detect-range-support","value":"0"},
{"category":1,"name":"fflags","value":"fastseek"},
{"category":2,"name":"skip_loop_filter","value":"48"},
{"category":4,"name":"reconnect","value":"1"},
{"category":4,"name":"enable-accurate-seek","value":"0"},
{"category":4,"name":"mediacodec","value":"1"},
{"category":4,"name":"mediacodec-auto-rotate","value":"1"},
{"category":4,"name":"mediacodec-handle-resolution-change","value":"1"},
{"category":4,"name":"mediacodec-hevc","value":"1"},
{"category":1,"name":"dns_cache_timeout","value":"600000000"}]}],
"ads":[
"mimg.0c1q0l.cn","www.googletagmanager.com","www.google-analytics.com","mc.usihnbcq.cn",
"mg.g1mm3d.cn","mscs.svaeuzh.cn","cnzz.hhttm.top","tp.vinuxhome.com","cnzz.mmstat.com",
"www.baihuillq.com","s23.cnzz.com","z3.cnzz.com","c.cnzz.com","stj.v1vo.top","z12.cnzz.com",
"img.mosflower.cn","tips.gamevvip.com","ehwe.yhdtns.com","xdn.cqqc3.com","www.jixunkyy.cn",
"sp.chemacid.cn","hm.baidu.com","s9.cnzz.com","z6.cnzz.com","um.cavuc.com","mav.mavuz.com",
"wofwk.aoidf3.com","z5.cnzz.com","xc.hubeijieshikj.cn","tj.tianwenhu.com","xg.gars57.cn","k.jinxiuzhilv.com",
"cdn.bootcss.com","ppl.xunzhuo123.com","xomk.jiangjunmh.top","img.xunzhuo123.com",
"z1.cnzz.com","s13.cnzz.com","xg.huataisangao.cn","z7.cnzz.com","xg.huataisangao.cn",
"z2.cnzz.com","s96.cnzz.com","q11.cnzz.com","thy.dacedsfa.cn","xg.whsbpw.cn","s19.cnzz.com",
"z8.cnzz.com","s4.cnzz.com","f5w.as12df.top","ae01.alicdn.com","www.92424.cn",
"k.wudejia.com","vivovip.mmszxc.top","qiu.xixiqiu.com","cdnjs.hnfenxun.com","cms.qdwght.com"]
}