mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-02-05 02:05:49 +00:00
More shape and wave rendering fixes.
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
if(ENABLE_TESTING)
|
||||
install(DIRECTORY
|
||||
tests
|
||||
DESTINATION "${PROJECTM_DATADIR_PATH}/presets"
|
||||
DESTINATION "presets"
|
||||
COMPONENT Tests
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -36,220 +36,148 @@
|
||||
#include "wipemalloc.h"
|
||||
|
||||
|
||||
|
||||
CustomShape::CustomShape() : Shape()
|
||||
CustomShape::CustomShape()
|
||||
: CustomShape(0)
|
||||
{
|
||||
CustomShape(0);
|
||||
}
|
||||
|
||||
CustomShape::CustomShape ( int _id ) : Shape()
|
||||
CustomShape::CustomShape(int _id)
|
||||
: Shape()
|
||||
{
|
||||
|
||||
Param * param;
|
||||
|
||||
this->id = _id;
|
||||
this->per_frame_count = 0;
|
||||
this->per_frame_count = 0;
|
||||
|
||||
/* Start: Load custom shape parameters */
|
||||
param = Param::new_param_float ( "r", P_FLAG_NONE, &this->r, NULL, 1.0, 0.0, 0.5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "g", P_FLAG_NONE, &this->g, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "b", P_FLAG_NONE, &this->b, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "a", P_FLAG_NONE, &this->a, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "border_r", P_FLAG_NONE, &this->border_r, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "border_g", P_FLAG_NONE, &this->border_g, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "border_b", P_FLAG_NONE, &this->border_b, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "border_a", P_FLAG_NONE, &this->border_a, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "r2", P_FLAG_NONE, &this->r2, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "g2", P_FLAG_NONE, &this->g2, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "b2", P_FLAG_NONE, &this->b2, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "a2", P_FLAG_NONE, &this->a2, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "x", P_FLAG_NONE, &this->x, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "y", P_FLAG_NONE, &this->y, NULL, 1.0, 0.0, .5 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_bool ( "thickoutline", P_FLAG_NONE, &this->thickOutline, 1, 0, 0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_bool ( "enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_int ( "sides", P_FLAG_NONE, &this->sides, 100, 3, 3 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_bool ( "additive", P_FLAG_NONE, &this->additive, 1, 0, 0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_bool ( "textured", P_FLAG_NONE, &this->textured, 1, 0, 0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "rad", P_FLAG_NONE, &this->radius, NULL, MAX_DOUBLE_SIZE, 0, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "ang", P_FLAG_NONE, &this->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "tex_zoom", P_FLAG_NONE, &this->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "tex_ang", P_FLAG_NONE, &this->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
/* Start: Load custom shape parameters */
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"r", P_FLAG_NONE, &this->r, nullptr, 1.0, 0.0, 0.5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"g", P_FLAG_NONE, &this->g, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"b", P_FLAG_NONE, &this->b, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"a", P_FLAG_NONE, &this->a, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"border_r", P_FLAG_NONE, &this->border_r, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"border_g", P_FLAG_NONE, &this->border_g, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"border_b", P_FLAG_NONE, &this->border_b, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"border_a", P_FLAG_NONE, &this->border_a, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"r2", P_FLAG_NONE, &this->r2, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"g2", P_FLAG_NONE, &this->g2, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"b2", P_FLAG_NONE, &this->b2, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"a2", P_FLAG_NONE, &this->a2, nullptr, 1.0, 0.0, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"x", P_FLAG_NONE, &this->x, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"y", P_FLAG_NONE, &this->y, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, .5), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"thickoutline", P_FLAG_NONE, &this->thickOutline, 1, 0, 0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_int(
|
||||
"sides", P_FLAG_NONE, &this->sides, 100, 3, 3), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"additive", P_FLAG_NONE, &this->additive, 1, 0, 0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"textured", P_FLAG_NONE, &this->textured, 1, 0, 0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_int(
|
||||
"num_inst", P_FLAG_NONE, &this->num_inst, 1000, 1, 1), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_int(
|
||||
"instance", P_FLAG_READONLY, &this->instance, 999, 0, 0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"rad", P_FLAG_NONE, &this->radius, nullptr, MAX_DOUBLE_SIZE, 0, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"ang", P_FLAG_NONE, &this->ang, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"tex_zoom", P_FLAG_NONE, &this->tex_zoom, nullptr, MAX_DOUBLE_SIZE, .00000000001, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"tex_ang", P_FLAG_NONE, &this->tex_ang, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t1", P_FLAG_TVAR, &this->t1, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t2", P_FLAG_TVAR, &this->t2, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t3", P_FLAG_TVAR, &this->t3, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t4", P_FLAG_TVAR, &this->t4, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t5", P_FLAG_TVAR, &this->t5, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t6", P_FLAG_TVAR, &this->t6, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t7", P_FLAG_TVAR, &this->t7, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t8", P_FLAG_TVAR, &this->t8, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
|
||||
param = Param::new_param_float ( "t1", P_FLAG_TVAR, &this->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t2", P_FLAG_TVAR, &this->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t3", P_FLAG_TVAR, &this->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t4", P_FLAG_TVAR, &this->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t5", P_FLAG_TVAR, &this->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t6", P_FLAG_TVAR, &this->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t7", P_FLAG_TVAR, &this->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
param = Param::new_param_float ( "t8", P_FLAG_TVAR, &this->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NUM_Q_VARIABLES;i++) {
|
||||
std::ostringstream os;
|
||||
os << "q" << i+1;
|
||||
param = Param::new_param_float ( os.str().c_str(), P_FLAG_QVAR, &this->q[i], NULL, MAX_DOUBLE_SIZE,
|
||||
-MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert ( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
param = Param::new_param_string ( "imageurl", P_FLAG_NONE, &this->imageUrl);
|
||||
if ( !ParamUtils::insert( param, &this->text_properties_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
for (unsigned int i = 0; i < NUM_Q_VARIABLES; i++)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "q" << i + 1;
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
os.str().c_str(), P_FLAG_QVAR, &this->q[i], nullptr,
|
||||
MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), &this->param_tree);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Frees a custom shape form object */
|
||||
CustomShape::~CustomShape()
|
||||
{
|
||||
|
||||
traverseVector<TraverseFunctors::Delete<PerFrameEqn> > ( per_frame_eqn_tree );
|
||||
traverse<TraverseFunctors::Delete<InitCond> > ( init_cond_tree );
|
||||
traverse<TraverseFunctors::Delete<Param> > ( param_tree );
|
||||
traverse<TraverseFunctors::Delete<InitCond> > ( per_frame_init_eqn_tree );
|
||||
traverse<TraverseFunctors::Delete<Param> > ( text_properties_tree );
|
||||
|
||||
traverseVector<TraverseFunctors::Delete<PerFrameEqn> >(per_frame_eqn_tree);
|
||||
traverse<TraverseFunctors::Delete<InitCond> >(init_cond_tree);
|
||||
traverse<TraverseFunctors::Delete<Param> >(param_tree);
|
||||
traverse<TraverseFunctors::Delete<InitCond> >(per_frame_init_eqn_tree);
|
||||
traverse<TraverseFunctors::Delete<Param> >(text_properties_tree);
|
||||
}
|
||||
|
||||
void CustomShape::loadUnspecInitConds()
|
||||
{
|
||||
|
||||
InitCondUtils::LoadUnspecInitCond fun ( this->init_cond_tree, this->per_frame_init_eqn_tree );
|
||||
traverse ( param_tree, fun );
|
||||
InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree);
|
||||
traverse(param_tree, fun);
|
||||
}
|
||||
|
||||
void CustomShape::evalInitConds()
|
||||
{
|
||||
// NOTE: This is verified to be same behavior as trunk
|
||||
for ( std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin();
|
||||
pos != per_frame_init_eqn_tree.end();++pos )
|
||||
pos->second->evaluate();
|
||||
for (auto& pos: per_frame_init_eqn_tree)
|
||||
{
|
||||
pos.second->evaluate();
|
||||
}
|
||||
|
||||
t1Init = t1;
|
||||
t2Init = t2;
|
||||
t3Init = t3;
|
||||
t4Init = t4;
|
||||
t5Init = t5;
|
||||
t6Init = t6;
|
||||
t7Init = t7;
|
||||
t8Init = t8;
|
||||
}
|
||||
|
||||
void CustomShape::Draw(RenderContext& context)
|
||||
{
|
||||
for (int i = 0; i < num_inst; i++)
|
||||
{
|
||||
t1 = t1Init;
|
||||
t2 = t2Init;
|
||||
t3 = t3Init;
|
||||
t4 = t4Init;
|
||||
t5 = t5Init;
|
||||
t6 = t6Init;
|
||||
t7 = t7Init;
|
||||
t8 = t8Init;
|
||||
instance = i;
|
||||
|
||||
for (auto& pos: per_frame_eqn_tree)
|
||||
{
|
||||
pos->evaluate();
|
||||
}
|
||||
|
||||
Shape::Draw(context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#define _CUSTOM_SHAPE_H
|
||||
|
||||
#define CUSTOM_SHAPE_DEBUG 0
|
||||
|
||||
#include <map>
|
||||
#include "Param.hpp"
|
||||
#include "PerFrameEqn.hpp"
|
||||
@ -40,50 +41,68 @@
|
||||
class Preset;
|
||||
|
||||
|
||||
class CustomShape : public Shape {
|
||||
class CustomShape : public Shape
|
||||
{
|
||||
public:
|
||||
/* Numerical id */
|
||||
int id;
|
||||
int per_frame_count;
|
||||
int id{ 0 };
|
||||
int per_frame_count{ 0 };
|
||||
|
||||
/* Parameter tree associated with this custom shape */
|
||||
std::map<std::string,Param*> param_tree;
|
||||
std::map<std::string, Param*> param_tree;
|
||||
|
||||
/* Engine variables */
|
||||
|
||||
bool enabled;
|
||||
bool enabled{ false };
|
||||
|
||||
int num_inst{ 1 }; //!< Number of shape instances to render
|
||||
int instance{ 0 }; //!< Currently rendered instance
|
||||
|
||||
/* stupid t variables */
|
||||
float t1;
|
||||
float t2;
|
||||
float t3;
|
||||
float t4;
|
||||
float t5;
|
||||
float t6;
|
||||
float t7;
|
||||
float t8;
|
||||
float t1{ 0.0f };
|
||||
float t2{ 0.0f };
|
||||
float t3{ 0.0f };
|
||||
float t4{ 0.0f };
|
||||
float t5{ 0.0f };
|
||||
float t6{ 0.0f };
|
||||
float t7{ 0.0f };
|
||||
float t8{ 0.0f };
|
||||
|
||||
float t1Init{ 0.0f };
|
||||
float t2Init{ 0.0f };
|
||||
float t3Init{ 0.0f };
|
||||
float t4Init{ 0.0f };
|
||||
float t5Init{ 0.0f };
|
||||
float t6Init{ 0.0f };
|
||||
float t7Init{ 0.0f };
|
||||
float t8Init{ 0.0f };
|
||||
|
||||
/* stupider q variables */
|
||||
float q[NUM_Q_VARIABLES];
|
||||
float q[NUM_Q_VARIABLES]{};
|
||||
|
||||
// Data structure to hold per frame / per frame init equations
|
||||
std::map<std::string,InitCond*> init_cond_tree;
|
||||
std::vector<PerFrameEqn*> per_frame_eqn_tree;
|
||||
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
|
||||
std::map<std::string, InitCond*> init_cond_tree;
|
||||
std::vector<PerFrameEqn*> per_frame_eqn_tree;
|
||||
std::map<std::string, InitCond*> per_frame_init_eqn_tree;
|
||||
|
||||
std::map<std::string, Param*> text_properties_tree;
|
||||
|
||||
|
||||
/// Allocate a new custom shape, including param associations, per point equations, and initial values.
|
||||
/// \param id an integer id to associate with this custom wave. Future line parsing uses this as a reference key.
|
||||
CustomShape(int _id );
|
||||
CustomShape(int _id);
|
||||
|
||||
CustomShape();
|
||||
|
||||
virtual ~CustomShape();
|
||||
|
||||
void loadUnspecInitConds();
|
||||
|
||||
void evalInitConds();
|
||||
|
||||
};
|
||||
void Draw(RenderContext& context) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /** !_CUSTOM_SHAPE_H */
|
||||
|
||||
@ -43,469 +43,165 @@
|
||||
#define MAX_SAMPLE_SIZE 4096
|
||||
|
||||
|
||||
CustomWave::CustomWave(int _id) : Waveform(512),
|
||||
id(_id),
|
||||
per_frame_count(0),
|
||||
r(0),
|
||||
g(0),
|
||||
b(0),
|
||||
a(0),
|
||||
per_point_program(nullptr)
|
||||
CustomWave::CustomWave(int _id)
|
||||
: Waveform(512)
|
||||
, id(_id)
|
||||
{
|
||||
this->r_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
this->g_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
this->b_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
this->a_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
this->x_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
this->y_mesh.resize(MAX_SAMPLE_SIZE);
|
||||
|
||||
/* Start: Load custom wave parameters */
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"r", P_FLAG_NONE | P_FLAG_PER_POINT, &r, r_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"g", P_FLAG_NONE | P_FLAG_PER_POINT, &g, g_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"b", P_FLAG_NONE | P_FLAG_PER_POINT, &b, b_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"a", P_FLAG_NONE | P_FLAG_PER_POINT, &this->a, this->a_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"x", P_FLAG_NONE | P_FLAG_PER_POINT, &this->x, this->x_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"y", P_FLAG_NONE | P_FLAG_PER_POINT, &this->y, this->y_mesh.data(), 1.0, 0.0, .5), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_int(
|
||||
"sep", P_FLAG_NONE, &this->sep, 100, -100, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"bspectrum", P_FLAG_NONE, &this->spectrum, 1, 0, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"bdrawthick", P_FLAG_NONE, &this->thick, 1, 0, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"busedots", P_FLAG_NONE, &this->dots, 1, 0, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_bool(
|
||||
"badditive", P_FLAG_NONE, &this->additive, 1, 0, 0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_int(
|
||||
"samples", P_FLAG_NONE, &this->samples, 2048, 1, 512), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"sample", P_FLAG_READONLY | P_FLAG_NONE, &this->sample, nullptr, 1.0, 0.0, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"value1", P_FLAG_READONLY | P_FLAG_NONE, &this->v1, nullptr, 1.0, -1.0, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"value2", P_FLAG_READONLY | P_FLAG_NONE, &this->v2, nullptr, 1.0, -1.0, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"smoothing", P_FLAG_NONE, &this->smoothing, nullptr, 1.0, 0.0, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"scaling", P_FLAG_NONE, &this->scaling, nullptr, MAX_DOUBLE_SIZE, 0.0, 1.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t1", P_FLAG_TVAR, &this->t1, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t2", P_FLAG_TVAR, &this->t2, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t3", P_FLAG_TVAR, &this->t3, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t4", P_FLAG_TVAR, &this->t4, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t5", P_FLAG_TVAR, &this->t5, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t6", P_FLAG_TVAR, &this->t6, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0),¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t7", P_FLAG_TVAR, &this->t7, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
"t8", P_FLAG_TVAR, &this->t8, nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0), ¶m_tree);
|
||||
|
||||
for (unsigned int i = 0; i < NUM_Q_VARIABLES; i++)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "q" << i + 1;
|
||||
ParamUtils::insert(Param::new_param_float(
|
||||
os.str().c_str(), P_FLAG_QVAR, &this->q[i], nullptr, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE,0.0), &this->param_tree);
|
||||
}
|
||||
|
||||
Param * param;
|
||||
|
||||
/// @bug deprecate the use of wipemalloc
|
||||
this->r_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
this->g_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
this->b_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
this->a_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
this->x_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
this->y_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
|
||||
|
||||
/* Start: Load custom wave parameters */
|
||||
|
||||
if ((param = Param::new_param_float("r", P_FLAG_NONE | P_FLAG_PER_POINT, &this->r, this->r_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, ¶m_tree))
|
||||
{
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("g", P_FLAG_NONE | P_FLAG_PER_POINT, &this->g, this->g_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, ¶m_tree))
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("b", P_FLAG_NONE | P_FLAG_PER_POINT, &this->b, this->b_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("a", P_FLAG_NONE | P_FLAG_PER_POINT, &this->a, this->a_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("x", P_FLAG_NONE | P_FLAG_PER_POINT, &this->x, this->x_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("y", P_FLAG_NONE | P_FLAG_PER_POINT, &this->y, this->y_mesh, 1.0, 0.0, .5)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_bool("enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_int("sep", P_FLAG_NONE, &this->sep, 100, -100, 0)) == NULL)
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_bool("bspectrum", P_FLAG_NONE, &this->spectrum, 1, 0, 0)) == NULL)
|
||||
{
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_bool("bdrawthick", P_FLAG_NONE, &this->thick, 1, 0, 0)) == NULL)
|
||||
{
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
/// @bug make exception
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_bool("busedots", P_FLAG_NONE, &this->dots, 1, 0, 0)) == NULL)
|
||||
{
|
||||
|
||||
/// @bug make exception
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_bool("badditive", P_FLAG_NONE, &this->additive, 1, 0, 0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_int("samples", P_FLAG_NONE, &this->samples, 2048, 1, 512)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("sample", P_FLAG_READONLY | P_FLAG_NONE,
|
||||
&this->sample, NULL, 1.0, 0.0, 0.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("value1", P_FLAG_READONLY | P_FLAG_NONE, &this->v1, NULL, 1.0, -1.0, 0.0)) == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("value2", P_FLAG_READONLY | P_FLAG_NONE, &this->v2, NULL, 1.0, -1.0, 0.0)) == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("smoothing", P_FLAG_NONE, &this->smoothing, NULL, 1.0, 0.0, 0.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("scaling", P_FLAG_NONE, &this->scaling, NULL, MAX_DOUBLE_SIZE, 0.0, 1.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("t1", P_FLAG_TVAR, &this->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("t2", P_FLAG_TVAR, &this->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("t3", P_FLAG_TVAR, &this->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
if ((param = Param::new_param_float("t4", P_FLAG_TVAR, &this->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
if ((param = Param::new_param_float("t5", P_FLAG_TVAR, &this->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("t6", P_FLAG_TVAR, &this->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
if ((param = Param::new_param_float("t7", P_FLAG_TVAR, &this->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if ((param = Param::new_param_float("t8", P_FLAG_TVAR, &this->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ParamUtils::insert(param, &this->param_tree))
|
||||
{
|
||||
;
|
||||
abort();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NUM_Q_VARIABLES;i++) {
|
||||
std::ostringstream os;
|
||||
os << "q" << i+1;
|
||||
param = Param::new_param_float ( os.str().c_str(), P_FLAG_QVAR, &this->q[i], NULL, MAX_DOUBLE_SIZE,
|
||||
-MAX_DOUBLE_SIZE, 0.0 );
|
||||
if ( !ParamUtils::insert ( param, &this->param_tree ) )
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* End of parameter loading. Note that the read only parameters associated
|
||||
with custom waves (ie, sample) are variables stored in PresetFrameIO.hpp,
|
||||
and not specific to the custom wave datastructure. */
|
||||
|
||||
and not specific to the custom wave data structure. */
|
||||
}
|
||||
|
||||
CustomWave::~CustomWave()
|
||||
{
|
||||
for (const auto& eqn : per_point_eqn_tree)
|
||||
{
|
||||
delete eqn;
|
||||
}
|
||||
|
||||
for (const auto& eqn : per_frame_eqn_tree)
|
||||
{
|
||||
delete eqn;
|
||||
}
|
||||
|
||||
for (std::vector<PerPointEqn*>::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end(); ++pos)
|
||||
delete(*pos);
|
||||
for (const auto& cond : init_cond_tree)
|
||||
{
|
||||
delete cond.second;
|
||||
}
|
||||
|
||||
for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
|
||||
delete(*pos);
|
||||
for (const auto& cond : per_frame_init_eqn_tree)
|
||||
{
|
||||
delete cond.second;
|
||||
}
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
|
||||
delete(pos->second);
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
|
||||
delete(pos->second);
|
||||
|
||||
for (std::map<std::string, Param*>::iterator pos = param_tree.begin(); pos != param_tree.end(); ++pos)
|
||||
delete(pos->second);
|
||||
|
||||
free(r_mesh);
|
||||
free(g_mesh);
|
||||
free(b_mesh);
|
||||
free(a_mesh);
|
||||
free(x_mesh);
|
||||
free(y_mesh);
|
||||
for (const auto& param : param_tree)
|
||||
{
|
||||
delete param.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Comments: index is not passed, so we assume monotonic increment by 1 is ok here
|
||||
int CustomWave::add_per_point_eqn(char * name, Expr * gen_expr)
|
||||
int CustomWave::add_per_point_eqn(char* name, Expr* gen_expr)
|
||||
{
|
||||
/* Argument checks */
|
||||
if (!gen_expr || !name)
|
||||
{
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
PerPointEqn * per_point_eqn;
|
||||
int index;
|
||||
Param * param = NULL;
|
||||
if (CUSTOM_WAVE_DEBUG)
|
||||
{
|
||||
printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
|
||||
}
|
||||
|
||||
/* Argument checks */
|
||||
if (gen_expr == NULL)
|
||||
return PROJECTM_FAILURE;
|
||||
if (name == NULL)
|
||||
return PROJECTM_FAILURE;
|
||||
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
|
||||
auto param = ParamUtils::find<ParamUtils::AUTO_CREATE>(name, ¶m_tree);
|
||||
if (!param)
|
||||
{
|
||||
if (CUSTOM_WAVE_DEBUG)
|
||||
{
|
||||
printf("add_per_point_eqn: failed to allocate a new parameter!\n");
|
||||
}
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
|
||||
/* Get largest index in the tree */
|
||||
per_point_eqn_tree.push_back(new PerPointEqn(static_cast<int>(per_point_eqn_tree.size()), param, gen_expr));
|
||||
|
||||
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
|
||||
|
||||
if ((param = ParamUtils::find<ParamUtils::AUTO_CREATE>(name,¶m_tree)) == NULL)
|
||||
{
|
||||
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: failed to allocate a new parameter!\n");
|
||||
return PROJECTM_FAILURE;
|
||||
|
||||
}
|
||||
|
||||
/* Get largest index in the tree */
|
||||
index = per_point_eqn_tree.size();
|
||||
|
||||
/* Create the per point equation given the index, parameter, and general expression */
|
||||
if ((per_point_eqn = new PerPointEqn(index, param, gen_expr)) == NULL)
|
||||
return PROJECTM_FAILURE;
|
||||
if (CUSTOM_WAVE_DEBUG)
|
||||
printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, param->name.c_str());
|
||||
|
||||
/* Insert the per pixel equation into the preset per pixel database */
|
||||
|
||||
per_point_eqn_tree.push_back(per_point_eqn);
|
||||
|
||||
/* Done */
|
||||
return PROJECTM_SUCCESS;
|
||||
/* Done */
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void CustomWave::evalInitConds()
|
||||
{
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
|
||||
{
|
||||
assert(pos->second);
|
||||
pos->second->evaluate();
|
||||
}
|
||||
|
||||
for (auto& eqn: per_frame_init_eqn_tree)
|
||||
{
|
||||
assert(eqn.second);
|
||||
eqn.second->evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
ColoredPoint CustomWave::PerPoint(ColoredPoint p, const WaveformContext context)
|
||||
Waveform::ColoredPoint CustomWave::PerPoint(ColoredPoint p, const Context& context)
|
||||
{
|
||||
if (nullptr == per_point_program)
|
||||
if (!per_point_program)
|
||||
{
|
||||
// see comment in MilkdropPreset, collect a list of assignments into one ProgramExpr
|
||||
// which (theoretically) could be compiled together.
|
||||
std::vector<Expr *> steps;
|
||||
for (auto pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end();++pos)
|
||||
steps.push_back((*pos)->assign_expr);
|
||||
std::vector<Expr*> steps;
|
||||
for (const auto& eqn : per_point_eqn_tree)
|
||||
{
|
||||
steps.push_back(eqn->assign_expr);
|
||||
}
|
||||
Expr *program_expr = Expr::create_program_expr(steps, false);
|
||||
Expr *jit = nullptr;
|
||||
#if HAVE_LLVM
|
||||
|
||||
@ -18,109 +18,99 @@
|
||||
* See 'LICENSE.txt' included within this release
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* Encapsulation of a custom wave
|
||||
*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
#ifndef _CUSTOM_WAVE_H
|
||||
#define _CUSTOM_WAVE_H
|
||||
#pragma once
|
||||
|
||||
#define CUSTOM_WAVE_DEBUG 0
|
||||
|
||||
class CustomWave;
|
||||
class Expr;
|
||||
class PerPointEqn;
|
||||
class Preset;
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common.hpp"
|
||||
#include "Param.hpp"
|
||||
#include "PerFrameEqn.hpp"
|
||||
#include "Renderer/Waveform.hpp"
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
#include "MilkdropPresetFactory/Param.hpp"
|
||||
#include "MilkdropPresetFactory/PerFrameEqn.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class CustomWave : public Waveform
|
||||
{
|
||||
public:
|
||||
CustomWave() = delete;
|
||||
|
||||
/** Empty constructor leaves wave in undefined state **/
|
||||
//CustomWave() {}
|
||||
/**
|
||||
* @brief Initializes a custom waveform with the given ID
|
||||
* @param id The ID (index) of the custom wave.
|
||||
*/
|
||||
explicit CustomWave(int id);
|
||||
|
||||
/** Initializes a custom wave id given the integer id */
|
||||
CustomWave(int id);
|
||||
~CustomWave() override;
|
||||
|
||||
/** Destructor is necessary so we can free the per point matrices **/
|
||||
virtual ~CustomWave();
|
||||
int add_per_point_eqn(char* name, Expr* gen_expr);
|
||||
|
||||
ColoredPoint PerPoint(ColoredPoint p, const WaveformContext context);
|
||||
void evalCustomWaveInitConditions(Preset* preset);
|
||||
|
||||
void loadUnspecInitConds();
|
||||
|
||||
void evalInitConds();
|
||||
|
||||
ColoredPoint PerPoint(ColoredPoint p, const Context& context) override;
|
||||
|
||||
/* Numerical id */
|
||||
int id;
|
||||
int per_frame_count;
|
||||
int id{ 0 };
|
||||
int per_frame_count{ 0 };
|
||||
|
||||
/* Parameter tree associated with this custom wave */
|
||||
std::map<std::string,Param*> param_tree;
|
||||
|
||||
/* Engine variables */
|
||||
float x; /* x position for per point equations */
|
||||
float y; /* y position for per point equations */
|
||||
float r; /* red color value */
|
||||
float g; /* green color value */
|
||||
float b; /* blue color value */
|
||||
float a; /* alpha color value */
|
||||
float * x_mesh;
|
||||
float * y_mesh;
|
||||
float * r_mesh;
|
||||
float * b_mesh;
|
||||
float * g_mesh;
|
||||
float * a_mesh;
|
||||
float x{ 0.0f }; /* x position for per point equations */
|
||||
float y{ 0.0f }; /* y position for per point equations */
|
||||
float r{ 0.0f }; /* red color value */
|
||||
float g{ 0.0f }; /* green color value */
|
||||
float b{ 0.0f }; /* blue color value */
|
||||
float a{ 0.0f }; /* alpha color value */
|
||||
|
||||
bool enabled; /* if true then wave is visible, hidden otherwise */
|
||||
std::vector<float> x_mesh;
|
||||
std::vector<float> y_mesh;
|
||||
std::vector<float> r_mesh;
|
||||
std::vector<float> b_mesh;
|
||||
std::vector<float> g_mesh;
|
||||
std::vector<float> a_mesh;
|
||||
|
||||
float sample;
|
||||
bool enabled{ false }; /* if true then wave is visible, hidden otherwise */
|
||||
|
||||
float sample{ 0.0f };
|
||||
|
||||
/* stupid t variables */
|
||||
float t1;
|
||||
float t2;
|
||||
float t3;
|
||||
float t4;
|
||||
float t5;
|
||||
float t6;
|
||||
float t7;
|
||||
float t8;
|
||||
float t1{ 0.0f };
|
||||
float t2{ 0.0f };
|
||||
float t3{ 0.0f };
|
||||
float t4{ 0.0f };
|
||||
float t5{ 0.0f };
|
||||
float t6{ 0.0f };
|
||||
float t7{ 0.0f };
|
||||
float t8{ 0.0f };
|
||||
|
||||
|
||||
/* stupider q variables */
|
||||
float q[NUM_Q_VARIABLES];
|
||||
float q[NUM_Q_VARIABLES]{};
|
||||
|
||||
float v1,v2;
|
||||
float v2{ 0.0f};
|
||||
float v1{ 0.0f};
|
||||
|
||||
/* Data structures to hold per frame and per point equations */
|
||||
std::map<std::string,InitCond*> init_cond_tree;
|
||||
std::vector<PerFrameEqn*> per_frame_eqn_tree;
|
||||
std::vector<PerPointEqn*> per_point_eqn_tree;
|
||||
Expr *per_point_program;
|
||||
Expr* per_point_program{ nullptr };
|
||||
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
|
||||
|
||||
/* Denotes the index of the last character for each string buffer */
|
||||
int per_point_eqn_string_index;
|
||||
int per_frame_eqn_string_index;
|
||||
int per_frame_init_eqn_string_index;
|
||||
|
||||
int add_per_point_eqn(char * name, Expr * gen_expr);
|
||||
void evalCustomWaveInitConditions(Preset *preset);
|
||||
|
||||
|
||||
void loadUnspecInitConds();
|
||||
|
||||
void evalInitConds();
|
||||
|
||||
};
|
||||
|
||||
#endif /** !_CUSTOM_WAVE_H */
|
||||
|
||||
@ -107,9 +107,13 @@ Param* Param::new_param_float(const char* name, short int flags, void* engine_va
|
||||
{
|
||||
assert(engine_val);
|
||||
|
||||
CValue iv{ .float_val = init_val };
|
||||
CValue ub{ .float_val = upper_bound };
|
||||
CValue lb{ .float_val = lower_bound };
|
||||
CValue iv;
|
||||
CValue ub;
|
||||
CValue lb;
|
||||
|
||||
iv.float_val = init_val;
|
||||
ub.float_val = upper_bound;
|
||||
lb.float_val = lower_bound;
|
||||
|
||||
return Param::create(name, P_TYPE_DOUBLE, flags, engine_val, matrix,iv, ub, lb);
|
||||
}
|
||||
@ -120,9 +124,13 @@ Param* Param::new_param_int(const char* name, short int flags, void* engine_val,
|
||||
{
|
||||
assert(engine_val);
|
||||
|
||||
CValue iv{ .int_val = init_val };
|
||||
CValue ub{ .int_val = upper_bound };
|
||||
CValue lb{ .int_val = lower_bound };
|
||||
CValue iv;
|
||||
CValue ub;
|
||||
CValue lb;
|
||||
|
||||
iv.int_val = init_val;
|
||||
ub.int_val = upper_bound;
|
||||
lb.int_val = lower_bound;
|
||||
|
||||
return Param::create(name, P_TYPE_INT, flags, engine_val, nullptr, iv, ub, lb);
|
||||
}
|
||||
@ -133,9 +141,13 @@ Param* Param::new_param_bool(const char* name, short int flags, void* engine_val
|
||||
{
|
||||
assert(engine_val);
|
||||
|
||||
CValue iv{ .bool_val = init_val };
|
||||
CValue ub{ .bool_val = upper_bound };
|
||||
CValue lb{ .bool_val = lower_bound };
|
||||
CValue iv;
|
||||
CValue ub;
|
||||
CValue lb;
|
||||
|
||||
iv.bool_val = init_val;
|
||||
ub.bool_val = upper_bound;
|
||||
lb.bool_val = lower_bound;
|
||||
|
||||
return Param::create(name, P_TYPE_BOOL, flags, engine_val, nullptr, iv, ub, lb);
|
||||
}
|
||||
@ -145,9 +157,13 @@ Param* Param::new_param_string(const char* name, short int flags, void* engine_v
|
||||
{
|
||||
assert(engine_val);
|
||||
|
||||
CValue iv{ .bool_val = false };
|
||||
CValue ub{ .bool_val = false };
|
||||
CValue lb{ .bool_val = false };
|
||||
CValue iv;
|
||||
CValue ub;
|
||||
CValue lb;
|
||||
|
||||
iv.bool_val = false;
|
||||
ub.bool_val = false;
|
||||
lb.bool_val = false;
|
||||
|
||||
return Param::create(name, P_TYPE_STRING, flags, engine_val, nullptr, iv, ub, lb);
|
||||
}
|
||||
|
||||
@ -269,11 +269,6 @@ void MilkdropWaveform::WaveformMath(RenderContext& context)
|
||||
}
|
||||
}
|
||||
|
||||
float r2, theta;
|
||||
|
||||
float wave_x_temp{ 0.0f };
|
||||
float wave_y_temp{ 0.0f };
|
||||
|
||||
// Aspect multipliers
|
||||
float aspectX{ 1.0f };
|
||||
float aspectY{ 1.0f };
|
||||
@ -287,8 +282,6 @@ void MilkdropWaveform::WaveformMath(RenderContext& context)
|
||||
aspectX = static_cast<float>(context.viewportSizeX) / static_cast<float>(context.viewportSizeY);
|
||||
}
|
||||
|
||||
const float temp_y = -1 * (y - 1.0f);
|
||||
|
||||
loop = false;
|
||||
|
||||
float mysteryWaveParam = mystery;
|
||||
|
||||
@ -16,8 +16,10 @@ public:
|
||||
int texsize{ 512 }; //!< Size of the internal render texture.
|
||||
int viewportSizeX{ 0 }; //!< Horizontal viewport size in pixels
|
||||
int viewportSizeY{ 0 }; //!< Vertical viewport size in pixels
|
||||
float aspectRatio{ 1.0 }; //!< X aspect ratio.
|
||||
bool aspectCorrect{ false }; //!< Aspect ratio correction.
|
||||
float aspectX{ 1.0 }; //!< X aspect ratio.
|
||||
float aspectY{ 1.0 }; //!< Y aspect ratio.
|
||||
float invAspectX{ 1.0 }; //!< Inverse X aspect ratio.
|
||||
float invAspectY{ 1.0 }; //!< Inverse Y aspect ratio.
|
||||
BeatDetect *beatDetect{ nullptr }; //!< Beat detection class to retrieve beat-related values.
|
||||
TextureManager *textureManager{ nullptr }; //!< Holds all loaded textures for shader access.
|
||||
GLuint programID_v2f_c4f{ 0 }; //!< Vertex shader program ID (no texture coordinates)
|
||||
|
||||
@ -208,8 +208,10 @@ void Renderer::RenderItems(const Pipeline& pipeline, const PipelineContext& pipe
|
||||
renderContext.texsize = nearestPower2(std::max(texsizeX, texsizeY));
|
||||
renderContext.viewportSizeX = vw;
|
||||
renderContext.viewportSizeY = vh;
|
||||
renderContext.aspectCorrect = correction;
|
||||
renderContext.aspectRatio = aspect;
|
||||
renderContext.aspectX = m_fAspectX;
|
||||
renderContext.aspectY = m_fAspectY;
|
||||
renderContext.invAspectX = m_fInvAspectX;
|
||||
renderContext.invAspectY = m_fInvAspectY;
|
||||
renderContext.textureManager = textureManager;
|
||||
renderContext.beatDetect = beatDetect;
|
||||
|
||||
@ -477,6 +479,9 @@ void Renderer::reset(int w, int h)
|
||||
m_fAspectX = (texsizeY > texsizeX) ? static_cast<float>(texsizeX) / static_cast<float>(texsizeY) : 1.0f;
|
||||
m_fAspectY = (texsizeX > texsizeY) ? static_cast<float>(texsizeY) / static_cast<float>(texsizeX) : 1.0f;
|
||||
|
||||
m_fInvAspectX = 1.0f / m_fAspectX;
|
||||
m_fInvAspectY = 1.0f / m_fAspectY;
|
||||
|
||||
InitCompositeShaderVertex();
|
||||
|
||||
if (textureManager != nullptr)
|
||||
@ -840,6 +845,7 @@ void Renderer::draw_stats()
|
||||
stats += "Resolution: " + std::to_string(vw) + "x" + std::to_string(vh) + "\n";
|
||||
stats += "Mesh X: " + std::to_string(mesh.width) + "\n";
|
||||
stats += "Mesh Y: " + std::to_string(mesh.height) + "\n";
|
||||
stats += "Time: " + std::to_string(renderContext.time) + "\n";
|
||||
|
||||
stats += "\n";
|
||||
stats += "Beat Detect:""\n";
|
||||
|
||||
@ -57,76 +57,60 @@ void Shape::InitVertexAttrib()
|
||||
|
||||
void Shape::Draw(RenderContext& context)
|
||||
{
|
||||
float xval{ x };
|
||||
float yval{ -(y - 1) };
|
||||
float t;
|
||||
|
||||
float temp_radius{ radius * (.707f * .707f * .707f * 1.04f) };
|
||||
constexpr float pi = 3.141592653589793f;
|
||||
|
||||
// Additive Drawing or Overwrite
|
||||
if (additive == 0)
|
||||
glBlendFunc(GL_SRC_ALPHA, additive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
std::vector<ShapeVertexShaderData> vertexData(sides + 2);
|
||||
|
||||
vertexData[0].color_r = r;
|
||||
vertexData[0].color_g = g;
|
||||
vertexData[0].color_b = b;
|
||||
vertexData[0].color_a = a * masterAlpha;
|
||||
vertexData[0].tex_x = 0.5;
|
||||
vertexData[0].tex_y = 0.5;
|
||||
vertexData[0].point_x = x;
|
||||
vertexData[0].point_y = -(y - 1.0f);
|
||||
|
||||
for (int i = 1; i < sides + 1; i++)
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
float cornerProgress = static_cast<float>(i - 1) / static_cast<float>(sides);
|
||||
float angle = cornerProgress * pi * 2.0f + ang + pi * 0.25f;
|
||||
|
||||
vertexData[i].color_r = r2;
|
||||
vertexData[i].color_g = g2;
|
||||
vertexData[i].color_b = b2;
|
||||
vertexData[i].color_a = a2 * masterAlpha;
|
||||
// Todo: There's still some issue with aspect ratio here, as everything gets squashed horizontally if Y > x.
|
||||
vertexData[i].point_x = vertexData[0].point_x + radius * 0.5f * cosf(angle) * context.aspectY;
|
||||
vertexData[i].point_y = vertexData[0].point_y + radius * 0.5f * sinf(angle);
|
||||
}
|
||||
|
||||
auto vertexData = new ShapeVertexShaderData[sides + 2];
|
||||
// Duplicate last vertex.
|
||||
vertexData[sides + 1] = vertexData[1];
|
||||
|
||||
if (textured)
|
||||
{
|
||||
if (!imageUrl.empty())
|
||||
{
|
||||
TextureSamplerDesc tex = context.textureManager->getTexture(imageUrl, GL_CLAMP_TO_EDGE, GL_LINEAR);
|
||||
if (tex.first != NULL)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.first->texID);
|
||||
glBindSampler(0, tex.second->samplerID);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, context.textureManager->getMainTexture()->texID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
context.aspectRatio = 1.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int i = 1; i < sides + 1; i++)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, context.textureManager->getMainTexture()->texID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
float cornerProgress = static_cast<float>(i - 1) / static_cast<float>(sides);
|
||||
|
||||
vertexData[i].tex_x =
|
||||
0.5f + 0.5f * cosf(cornerProgress * pi * 2.0f + ang + pi * 0.25f) / tex_zoom * context.aspectY;
|
||||
vertexData[i].tex_y = 0.5f + 0.5f * sinf(cornerProgress * pi * 2.0f + ang + pi * 0.25f) / tex_zoom;
|
||||
}
|
||||
|
||||
// Define the center point of the shape
|
||||
vertexData[0].color_r = r;
|
||||
vertexData[0].color_g = g;
|
||||
vertexData[0].color_b = b;
|
||||
vertexData[0].color_a = a * masterAlpha;
|
||||
vertexData[0].tex_x = 0.5;
|
||||
vertexData[0].tex_y = 0.5;
|
||||
vertexData[0].point_x = xval;
|
||||
vertexData[0].point_y = yval;
|
||||
|
||||
for (int i = 1; i < sides + 2; i++)
|
||||
{
|
||||
vertexData[i].color_r = r2;
|
||||
vertexData[i].color_g = g2;
|
||||
vertexData[i].color_b = b2;
|
||||
vertexData[i].color_a = a2 * masterAlpha;
|
||||
|
||||
t = static_cast<float>(i - 1) / static_cast<float>(sides);
|
||||
vertexData[i].tex_x = 0.5f + 0.5f * cosf(t * 3.1415927f * 2 + tex_ang + 3.1415927f * 0.25f) *
|
||||
(context.aspectCorrect ? context.aspectRatio : 1.0) / tex_zoom;
|
||||
vertexData[i].tex_y = 0.5f + 0.5f * sinf(t * 3.1415927f * 2 + tex_ang + 3.1415927f * 0.25f) / tex_zoom;
|
||||
vertexData[i].point_x = temp_radius * cosf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) *
|
||||
(context.aspectCorrect ? context.aspectRatio : 1.0) + xval;
|
||||
vertexData[i].point_y = temp_radius * sinf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) + yval;
|
||||
}
|
||||
vertexData[sides + 1] = vertexData[1];
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID_texture);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), vertexData, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), vertexData.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f_t2f);
|
||||
|
||||
@ -144,30 +128,9 @@ void Shape::Draw(RenderContext& context)
|
||||
else
|
||||
{//Untextured (use color values)
|
||||
|
||||
//Define the center point of the shape
|
||||
vertexData[0].color_r = r;
|
||||
vertexData[0].color_g = g;
|
||||
vertexData[0].color_b = b;
|
||||
vertexData[0].color_a = a * masterAlpha;
|
||||
vertexData[0].point_x = xval;
|
||||
vertexData[0].point_y = yval;
|
||||
|
||||
for (int i = 1; i < sides + 2; i++)
|
||||
{
|
||||
vertexData[i].color_r = r2;
|
||||
vertexData[i].color_g = g2;
|
||||
vertexData[i].color_b = b2;
|
||||
vertexData[i].color_a = a2 * masterAlpha;
|
||||
t = static_cast<float>(i - 1) / static_cast<float>(sides);
|
||||
vertexData[i].point_x = temp_radius * cosf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) *
|
||||
(context.aspectCorrect ? context.aspectRatio : 1.0) + xval;
|
||||
vertexData[i].point_y = temp_radius * sinf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) + yval;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID_not_texture);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), vertexData, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (sides + 2), vertexData.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
@ -181,14 +144,12 @@ void Shape::Draw(RenderContext& context)
|
||||
|
||||
if (border_a > 0.0f)
|
||||
{
|
||||
auto points = new float[sides + 1][2];
|
||||
std::vector<ShapeVertex> points(sides + 1);
|
||||
|
||||
for (int i = 0; i < sides; i++)
|
||||
for (int i = 0; i < sides + 1; i++)
|
||||
{
|
||||
t = (i - 1) / (float) sides;
|
||||
points[i][0] = temp_radius * cosf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) *
|
||||
(context.aspectCorrect ? context.aspectRatio : 1.0) + xval;
|
||||
points[i][1] = temp_radius * sinf(t * 3.1415927f * 2 + ang + 3.1415927f * 0.25f) + yval;
|
||||
points[i].x = vertexData[i + 1].point_x;
|
||||
points[i].y = vertexData[i + 1].point_y;
|
||||
}
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
@ -221,37 +182,33 @@ void Shape::Draw(RenderContext& context)
|
||||
case 1:
|
||||
for (auto j = 0; j < sides + 1; j++)
|
||||
{
|
||||
points[j][0] += incrementX;
|
||||
points[j].x += incrementX;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (auto j = 0; j < sides + 1; j++)
|
||||
{
|
||||
points[j][1] += incrementY;
|
||||
points[j].y += incrementY;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (auto j = 0; j < sides + 1; j++)
|
||||
{
|
||||
points[j][0] -= incrementX;
|
||||
points[j].x -= incrementX;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floatPair) * (sides), points, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floatPair) * (sides), points.data(), GL_DYNAMIC_DRAW);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, sides);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
delete[] points;
|
||||
}
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glUseProgram(0);
|
||||
|
||||
delete[] vertexData;
|
||||
}
|
||||
|
||||
@ -67,6 +67,12 @@ private:
|
||||
float tex_y; //!< The vertex y (v) texture coordinate.
|
||||
};
|
||||
|
||||
struct ShapeVertex
|
||||
{
|
||||
float x{ .0f }; //!< The vertex X coordinate.
|
||||
float y{ .0f }; //!< The vertex Y coordinate.
|
||||
};
|
||||
|
||||
GLuint m_vboID_texture{ 0 }; //!< Vertex buffer object ID for a textured shape.
|
||||
GLuint m_vaoID_texture{ 0 }; //!< Vertex array object ID for a textured shape.
|
||||
|
||||
|
||||
@ -1,35 +1,20 @@
|
||||
/*
|
||||
* Waveform.hpp
|
||||
*
|
||||
* Created on: Jun 25, 2008
|
||||
* Author: pete
|
||||
*/
|
||||
|
||||
#include "projectM-opengl.h"
|
||||
#include "Waveform.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "BeatDetect.hpp"
|
||||
#include "ShaderEngine.hpp"
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <functional>
|
||||
#endif /** WIN32 */
|
||||
|
||||
typedef float floatPair[2];
|
||||
|
||||
Waveform::Waveform(int _samples)
|
||||
: RenderItem(), samples(_samples), points(_samples), pointContext(_samples)
|
||||
: RenderItem()
|
||||
, samples(_samples)
|
||||
, points(_samples)
|
||||
{
|
||||
spectrum = false; /* spectrum data or pcm data */
|
||||
dots = false; /* draw wave as dots or lines */
|
||||
thick = false; /* draw thicker lines */
|
||||
additive = false; /* add color values together */
|
||||
|
||||
scaling= 1; /* scale factor of waveform */
|
||||
smoothing = 0; /* smooth factor of waveform */
|
||||
sep = 0;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
@ -47,49 +32,70 @@ void Waveform::Draw(RenderContext &context)
|
||||
const float vol_scale = context.beatDetect->getPCMScale();
|
||||
|
||||
// Make sure samples<=points.size(). We could reallocate points, but 512 is probably big enough.
|
||||
size_t samples_count = this->samples;
|
||||
if (samples_count > this->points.size())
|
||||
samples_count = this->points.size();
|
||||
int sampleCount{ std::min(this->samples, static_cast<int>(this->points.size())) };
|
||||
|
||||
float pcmL[512]{ 0.0f };
|
||||
float pcmR[512]{ 0.0f };
|
||||
|
||||
float *value1 = new float[samples_count];
|
||||
float *value2 = new float[samples_count];
|
||||
if (spectrum)
|
||||
{
|
||||
context.beatDetect->pcm.getSpectrum( value1, CHANNEL_0, samples_count, smoothing );
|
||||
context.beatDetect->pcm.getSpectrum( value2, CHANNEL_1, samples_count, smoothing );
|
||||
context.beatDetect->pcm.getSpectrum(pcmL, CHANNEL_0, sampleCount, 0.0f );
|
||||
context.beatDetect->pcm.getSpectrum(pcmR, CHANNEL_1, sampleCount, 0.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
context.beatDetect->pcm.getPCM( value1, CHANNEL_0, samples_count, smoothing );
|
||||
context.beatDetect->pcm.getPCM( value2, CHANNEL_1, samples_count, smoothing );
|
||||
context.beatDetect->pcm.getPCM(pcmL, CHANNEL_0, sampleCount, 0.0f );
|
||||
context.beatDetect->pcm.getPCM(pcmR, CHANNEL_1, sampleCount, 0.0f );
|
||||
}
|
||||
|
||||
const float mult = scaling * vol_scale * (spectrum ? 0.005f : 1.0f);
|
||||
WaveformContext waveContext(samples_count, context.beatDetect);
|
||||
const float mult = scaling * vol_scale * (spectrum ? 0.05f : 1.0f);
|
||||
|
||||
for (size_t x=0;x< samples_count;x++)
|
||||
{
|
||||
waveContext.sample = x/(float)(samples_count - 1);
|
||||
waveContext.sample_int = x;
|
||||
waveContext.left = value1[x] * mult;
|
||||
waveContext.right = value2[x] * mult;
|
||||
// PCM data smoothing
|
||||
int offset1 = spectrum ? 0 : (512 - sampleCount) / 2 - sep / 2;
|
||||
int offset2 = spectrum ? 0 : (512 - sampleCount) / 2 + sep / 2;
|
||||
int t = spectrum ? (512 - sep) / static_cast<float>(sampleCount) : 1;
|
||||
float mix1 = std::pow(smoothing * 0.98f, 0.5f);
|
||||
float mix2 = 1.0f - mix1;
|
||||
|
||||
points[x] = PerPoint(points[x],waveContext);
|
||||
}
|
||||
float value1[512]{ 0.0f };
|
||||
float value2[512]{ 0.0f };
|
||||
|
||||
std::vector<ColoredPoint> points_transf = points;
|
||||
value1[0] = pcmL[offset1];
|
||||
value2[0] = pcmR[offset2];
|
||||
|
||||
for (std::vector<ColoredPoint>::iterator iter = points_transf.begin(); iter != points_transf.end(); ++iter) {
|
||||
(*iter).y = -( (*iter).y-1);
|
||||
(*iter).a *= masterAlpha;
|
||||
for (int j = 0; j < sampleCount; j++)
|
||||
{
|
||||
value1[j] = pcmL[static_cast<int>(j * t) + offset1] * mix2 + value1[j - 1] * mix1;
|
||||
value2[j] = pcmR[static_cast<int>(j * t) + offset2] * mix2 + value2[j - 1] * mix1;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
for (int j = sampleCount - 2; j >= 0; j--)
|
||||
{
|
||||
value1[j] = value1[j] * mix2 + value1[j + 1] * mix1;
|
||||
value2[j] = value2[j] * mix2 + value2[j + 1] * mix1;
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ColoredPoint) * samples_count, NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ColoredPoint) * samples_count, &points_transf[0], GL_DYNAMIC_DRAW);
|
||||
Context waveContext(sampleCount, context.beatDetect);
|
||||
std::vector<ColoredPoint> pointsTransformed(sampleCount);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
for (int x = 0; x < sampleCount; x++)
|
||||
{
|
||||
waveContext.sample = static_cast<float>(x) / static_cast<float>(sampleCount - 1);
|
||||
waveContext.sample_int = x;
|
||||
waveContext.left = value1[x] * mult;
|
||||
waveContext.right = value2[x] * mult;
|
||||
|
||||
pointsTransformed[x] = PerPoint(points[x], waveContext);
|
||||
}
|
||||
|
||||
for (auto& point : pointsTransformed)
|
||||
{
|
||||
point.y = 1.0f - point.y;
|
||||
point.a *= masterAlpha;
|
||||
}
|
||||
|
||||
std::vector<ColoredPoint> pointsSmoothed(sampleCount * 2);
|
||||
auto smoothedVertexCount = SmoothWave(pointsTransformed.data(), sampleCount, pointsSmoothed.data());
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
@ -98,36 +104,107 @@ void Waveform::Draw(RenderContext &context)
|
||||
if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (thick)
|
||||
{
|
||||
glLineWidth(context.texsize <= 512 ? 2 : 2*context.texsize/512);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glLineWidth(1);
|
||||
|
||||
#ifndef GL_TRANSITION
|
||||
glPointSize(context.texsize <= 512 ? 2 : 2*context.texsize/512);
|
||||
#endif
|
||||
glUniform1f(context.uniform_v2f_c4f_vertex_point_size, context.texsize <= 512 ? 2 : 2*context.texsize/512);
|
||||
}
|
||||
// Additive wave drawing (vice overwrite)
|
||||
if (additive == 1)
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glLineWidth(1);
|
||||
|
||||
#ifndef GL_TRANSITION
|
||||
glPointSize(context.texsize <= 512 ? 1 : context.texsize/512);
|
||||
#endif
|
||||
glUniform1f(context.uniform_v2f_c4f_vertex_point_size, context.texsize <= 512 ? 1 : context.texsize/512);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
// Always draw "thick" dots.
|
||||
auto iterations = thick || dots ? 4 : 1;
|
||||
|
||||
// Need to use +/- 1.0 here instead of 2.0 used in Milkdrop to achieve the same rendering result.
|
||||
auto incrementX = 1.0f / static_cast<float>(context.viewportSizeX);
|
||||
auto incrementY = 1.0f / static_cast<float>(context.viewportSizeY);
|
||||
|
||||
GLuint drawType = dots ? GL_POINTS : GL_LINE_STRIP;
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
if (dots) glDrawArrays(GL_POINTS,0,samples_count);
|
||||
else glDrawArrays(GL_LINE_STRIP,0,samples_count);
|
||||
// If thick outline is used, draw the shape four times with slight offsets
|
||||
// (top left, top right, bottom right, bottom left).
|
||||
for (auto iteration = 0; iteration < iterations; iteration++)
|
||||
{
|
||||
switch (iteration)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
for (auto j = 0; j < smoothedVertexCount; j++)
|
||||
{
|
||||
pointsSmoothed[j].x += incrementX;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (auto j = 0; j < smoothedVertexCount; j++)
|
||||
{
|
||||
pointsSmoothed[j].y += incrementY;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (auto j = 0; j < smoothedVertexCount; j++)
|
||||
{
|
||||
pointsSmoothed[j].x -= incrementX;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ColoredPoint) * smoothedVertexCount, &pointsSmoothed[0], GL_DYNAMIC_DRAW);
|
||||
glDrawArrays(drawType, 0, smoothedVertexCount);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glLineWidth(context.texsize < 512 ? 1 : context.texsize/512);
|
||||
glUseProgram(0);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
delete[] value1;
|
||||
delete[] value2;
|
||||
}
|
||||
|
||||
int Waveform::SmoothWave(const Waveform::ColoredPoint* inputVertices, int vertexCount,
|
||||
Waveform::ColoredPoint* outputVertices)
|
||||
{
|
||||
constexpr float c1{ -0.15f };
|
||||
constexpr float c2{ 1.15f };
|
||||
constexpr float c3{ 1.15f };
|
||||
constexpr float c4{ -0.15f };
|
||||
constexpr float inverseSum{ 1.0f / (c1 + c2 + c3 + c4) };
|
||||
|
||||
int outputIndex = 0;
|
||||
int iBelow = 0;
|
||||
int iAbove2 = 1;
|
||||
|
||||
for (auto inputIndex = 0; inputIndex < vertexCount - 1; inputIndex++)
|
||||
{
|
||||
int iAbove = iAbove2;
|
||||
iAbove2 = std::min(vertexCount - 1, inputIndex + 2);
|
||||
outputVertices[outputIndex] = inputVertices[inputIndex];
|
||||
outputVertices[outputIndex + 1] = inputVertices[inputIndex];
|
||||
outputVertices[outputIndex + 1].x = (c1 * inputVertices[iBelow].x
|
||||
+ c2 * inputVertices[inputIndex].x
|
||||
+ c3 * inputVertices[iAbove].x
|
||||
+ c4 * inputVertices[iAbove2].x) * inverseSum;
|
||||
outputVertices[outputIndex + 1].y = (c1 * inputVertices[iBelow].y
|
||||
+ c2 * inputVertices[inputIndex].y
|
||||
+ c3 * inputVertices[iAbove].y
|
||||
+ c4 * inputVertices[iAbove2].y) * inverseSum;
|
||||
iBelow = inputIndex;
|
||||
outputIndex += 2;
|
||||
}
|
||||
|
||||
outputVertices[outputIndex] = inputVertices[vertexCount - 1];
|
||||
|
||||
return outputIndex + 1;
|
||||
}
|
||||
|
||||
@ -12,55 +12,87 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ColoredPoint
|
||||
{
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
|
||||
ColoredPoint():x(0.5),y(0.5),r(1),g(1),b(1),a(1){}
|
||||
};
|
||||
|
||||
class WaveformContext
|
||||
{
|
||||
public:
|
||||
float sample;
|
||||
int samples;
|
||||
int sample_int;
|
||||
float left;
|
||||
float right;
|
||||
BeatDetect *music;
|
||||
|
||||
WaveformContext(int _samples, BeatDetect *_music):samples(_samples),music(_music){}
|
||||
};
|
||||
|
||||
|
||||
class Waveform : public RenderItem
|
||||
{
|
||||
public:
|
||||
struct ColoredPoint
|
||||
{
|
||||
float x{ 0.5f }; //!< Vertex X coordinate.
|
||||
float y{ 0.5f }; //!< Vertex Y coordinate.
|
||||
float r{ 1.0f }; //!< Vertex red color value.
|
||||
float g{ 1.0f }; //!< Vertex green color value.
|
||||
float b{ 1.0f }; //!< Vertex blue color value.
|
||||
float a{ 1.0f }; //!< Vertex alpha value.
|
||||
};
|
||||
|
||||
int samples; /* number of samples associated with this wave form. Usually powers of 2 */
|
||||
bool spectrum; /* spectrum data or pcm data */
|
||||
bool dots; /* draw wave as dots or lines */
|
||||
bool thick; /* draw thicker lines */
|
||||
bool additive; /* add color values together */
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
float sample{ 0.0f }; //!< Current sample value.
|
||||
int samples{ 0 }; //!< Sample number
|
||||
int sample_int{ 0 }; //!< Sample integer value.
|
||||
float left{ 0.0f }; //!< Left channel value.
|
||||
float right{ 0.0f }; //!< Right channe value.
|
||||
BeatDetect* music{ nullptr }; //!< Beat detection instance.
|
||||
|
||||
float scaling; /* scale factor of waveform */
|
||||
float smoothing; /* smooth factor of waveform */
|
||||
int sep; /* no idea what this is yet... */
|
||||
/**
|
||||
* @brief Create a new context instance.
|
||||
* @param _samples Number of samples.
|
||||
* @param _music Beat detection instance, also used to access sample PCM data.
|
||||
*/
|
||||
Context(int _samples, BeatDetect* _music)
|
||||
: samples(_samples)
|
||||
, music(_music)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Waveform(int _samples);
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
/**
|
||||
* @brief Creates a new waveform with the given number of samples.
|
||||
* @param _samples The number of samples this waveform should display.
|
||||
*/
|
||||
explicit Waveform(int _samples);
|
||||
|
||||
private:
|
||||
virtual ColoredPoint PerPoint(ColoredPoint p, const WaveformContext context)=0;
|
||||
std::vector<ColoredPoint> points;
|
||||
std::vector<float> pointContext;
|
||||
/**
|
||||
* @brief Initializes the waveform's vertex buffer and attribute data.
|
||||
*/
|
||||
void InitVertexAttrib() override;
|
||||
|
||||
/**
|
||||
* @brief Renders the waveform.
|
||||
* @param context The rendering context instance.
|
||||
*/
|
||||
void Draw(RenderContext& context) override;
|
||||
|
||||
int samples{ 0 }; //!< Number of samples associated with this wave form. Usually powers of 2.
|
||||
bool spectrum{ false }; //!< Spectrum data or PCM data.
|
||||
bool dots{ false }; //!< If true, draw wave as dots instead of lines.
|
||||
bool thick{ false }; //!< Draw thicker lines.
|
||||
bool additive{ false }; //!< Add color values together.
|
||||
|
||||
float scaling{ 1.0f }; //!< Scale factor of waveform.
|
||||
float smoothing{ 0.0f }; //!< Smooth factor of waveform.
|
||||
int sep{ 0 }; //!< Separation distance of dual waveforms.
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Does a better-than-linear smooth on a wave.
|
||||
*
|
||||
* Roughly doubles the number of points.
|
||||
*
|
||||
* @param inputVertices Pointer to an array of vertices to be smoothed.
|
||||
* @param vertexCount Number of vertices/points in the input data.
|
||||
* @param outputVertices Pointer to a buffer that will receive the smoothed data. Must be able to hold 2 * vertexCount vertices.
|
||||
* @return The number of vertices in outputVertices after smoothing.
|
||||
*/
|
||||
static int SmoothWave(const ColoredPoint* inputVertices, int vertexCount, ColoredPoint* outputVertices);
|
||||
|
||||
virtual ColoredPoint PerPoint(ColoredPoint p, const Context& context) = 0;
|
||||
|
||||
std::vector<ColoredPoint> points; //!< Points in this waveform.
|
||||
};
|
||||
|
||||
#endif /* WAVEFORM_HPP_ */
|
||||
|
||||
Reference in New Issue
Block a user