<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 <NAME>
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
#define _NO_LIST_ID 0xffffffff

#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <string>
#include "common.h"
#include "global.h"
#include "TankSceneNode.h"
#include "ViewFrustum.h"
#include "SceneRenderer.h"
#include "StateDatabase.h"
#include "BZDBCache.h"


float curVertScale[3] = {1,1,1}; /// for the really lame #def
float curNormScale[3] = {1,1,1}; /// for the really lame #def

void doVertex3f(GLfloat x, GLfloat y, GLfloat z)
{
  glVertex3f(x * curVertScale[0], y * curVertScale[1], z * curVertScale[2]);
}

void doNormal3f(GLfloat x, GLfloat y, GLfloat z)
{
  const GLfloat d = hypotf(x * curNormScale[0],
    hypotf(y * curNormScale[1], z * curNormScale[2]));
  if (d > 1.0e-5f) {
    x *= curNormScale[0] / d;
    y *= curNormScale[1] / d;
    z *= curNormScale[2] / d;
  }
  glNormal3f(x, y, z);
}


class TankFactors
{
public:
       TankFactors()
       {
	 if (!callbackAdded) {
	     BZDB.addCallback(StateDatabase::BZDB_OBESEFACTOR, callback, NULL );
	     BZDB.addCallback(StateDatabase::BZDB_TINYFACTOR, callback, NULL );
	     BZDB.addCallback(StateDatabase::BZDB_THIEFTINYFACTOR, callback, NULL );
	     callbackAdded = true;
	 }
       }

       static void callback(const std::string& name, void*)
       {
	  if (name == StateDatabase::BZDB_OBESEFACTOR) {
	     styleFactors[1][0] = BZDB.eval(StateDatabase::BZDB_OBESEFACTOR);
	     styleFactors[1][1] = styleFactors[1][0];
	  }
	  else if (name == StateDatabase::BZDB_TINYFACTOR) {
	     styleFactors[2][0] = BZDB.eval(StateDatabase::BZDB_TINYFACTOR);
	     styleFactors[2][1] = styleFactors[2][0];
	  }
	  else if (name == StateDatabase::BZDB_THIEFTINYFACTOR) {
	     styleFactors[4][0] = BZDB.eval(StateDatabase::BZDB_THIEFTINYFACTOR);
	     styleFactors[4][1] = styleFactors[4][0];
	  }
       }

       //Modifiers for Normal, Obese. Tiny, Thin, Thief
       static GLfloat styleFactors[5][3];
       static bool callbackAdded;
};
bool TankFactors::callbackAdded = false;
GLfloat TankFactors::styleFactors[5][3] = {
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 0.001f, 1.0f },
			{ 1.0f, 1.0f, 1.0f }
		};

// parts: body, turret, barrel, left tread, right tread

const int		TankSceneNode::numLOD = 3;
int			TankSceneNode::maxLevel = numLOD;

TankSceneNode::TankSceneNode(const GLfloat pos[3], const GLfloat forward[3]) :
				useOverride(false),
				hidden(false),
				invisible(false),
				clip(false),
				style(TankRenderNode::Normal),
				lowRenderNode(this),
				medRenderNode(this),
				highRenderNode(this),
				shadowRenderNode(this)
{
  // setup style factors (BZDB isn't set up at global init time

  TankFactors(); // Install callbacks for styleFactors

			// prepare geometry
  move(pos, forward);
  baseRadius = 0.25f * (BZDB.eval(StateDatabase::BZDB_TANKLENGTH) * BZDB.eval(StateDatabase::BZDB_TANKLENGTH) +
			BZDB.eval(StateDatabase::BZDB_TANKWIDTH) * BZDB.eval(StateDatabase::BZDB_TANKWIDTH) +
			BZDBCache::tankHeight * BZDBCache::tankHeight);
  setRadius(baseRadius);

  color[3] = 1.0f;
  setColor(1.0f, 1.0f, 1.0f);
  setExplodeFraction(0.0f);

  shadowRenderNode.setShadow();
}

TankSceneNode::~TankSceneNode()
{
  // do nothing
}

void			TankSceneNode::setColor(
				GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
  color[0] = r;
  color[1] = g;
  color[2] = b;
  color[3] = a;
  transparent = (color[3] != 1.0f);
}

void			TankSceneNode::setColor(const GLfloat* rgba)
{
  color[0] = rgba[0];
  color[1] = rgba[1];
  color[2] = rgba[2];
  color[3] = rgba[3];
  transparent = (color[3] != 1.0f);
}

void			TankSceneNode::setMaterial(const OpenGLMaterial& mat)
{
  OpenGLGStateBuilder builder(gstate);
  builder.setMaterial(mat);
  gstate = builder.getState();
}

void			TankSceneNode::setTexture(const int texture)
{
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(texture);
  gstate = builder.getState();
}

void			TankSceneNode::move(const GLfloat pos[3],
					const GLfloat forward[3])
{
  azimuth = 180.0f / M_PI*atan2f(forward[1], forward[0]);
  elevation = -180.0f / M_PI*atan2f(forward[2], hypotf(forward[0],forward[1]));
  setCenter(pos);
}

void			TankSceneNode::notifyStyleChange()
{
  sort = !BZDB.isTrue("zbuffer");
  OpenGLGStateBuilder builder(gstate);
  builder.enableTexture(BZDBCache::texture);
  builder.enableMaterial(BZDB.isTrue("lighting"));
  builder.setSmoothing(BZDB.isTrue("smooth"));
  if (BZDBCache::blend && transparent) {
    builder.setBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    builder.setStipple(1.0f);
  }
  else {
    builder.resetBlending();
    builder.setStipple(transparent ? 0.5f : 1.0f);
  }
  gstate = builder.getState();

  OpenGLGStateBuilder builder2(lightsGState);
  if (BZDB.isTrue("smooth")) {
    builder2.setBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    builder2.setSmoothing();
  }
  else {
    builder2.resetBlending();
    builder2.setSmoothing(false);
  }
  lightsGState = builder2.getState();
}

void			TankSceneNode::addRenderNodes(
				SceneRenderer& renderer)
{
  // don't draw hidden tanks.  this is mainly to avoid drawing player's
  // tank when player is using view from tank.  can't simply not include
  // player, though, cos then we wouldn't get the tank's shadow.
  if (hidden || invisible) return;

  // pick level of detail
  TankRenderNode* node;
  const GLfloat* sphere = getSphere();
  const ViewFrustum& view = renderer.getViewFrustum();
  const float size = sphere[3] * view.getAreaFactor() /
					getDistance(view.getEye());
  if (maxLevel == -1)
    node = &highRenderNode;
  else if (maxLevel > 2 && size > 55.0f)
    node = &highRenderNode;
  else if (maxLevel > 1 && size > 25.0f)
    node = &medRenderNode;
  else node = &lowRenderNode;

  // if drawing in sorted order then decide which order<commit_msg>Using BZDB-Cache for overused DB accessed var<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 <NAME>
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
#define _NO_LIST_ID 0xffffffff

#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <string>
#include "common.h"
#include "global.h"
#include "TankSceneNode.h"
#include "ViewFrustum.h"
#include "SceneRenderer.h"
#include "StateDatabase.h"
#include "BZDBCache.h"


float curVertScale[3] = {1,1,1}; /// for the really lame #def
float curNormScale[3] = {1,1,1}; /// for the really lame #def

void doVertex3f(GLfloat x, GLfloat y, GLfloat z)
{
  glVertex3f(x * curVertScale[0], y * curVertScale[1], z * curVertScale[2]);
}

void doNormal3f(GLfloat x, GLfloat y, GLfloat z)
{
  const GLfloat d = hypotf(x * curNormScale[0],
    hypotf(y * curNormScale[1], z * curNormScale[2]));
  if (d > 1.0e-5f) {
    x *= curNormScale[0] / d;
    y *= curNormScale[1] / d;
    z *= curNormScale[2] / d;
  }
  glNormal3f(x, y, z);
}


class TankFactors
{
public:
       TankFactors()
       {
	 if (!callbackAdded) {
	     BZDB.addCallback(StateDatabase::BZDB_OBESEFACTOR, callback, NULL );
	     BZDB.addCallback(StateDatabase::BZDB_TINYFACTOR, callback, NULL );
	     BZDB.addCallback(StateDatabase::BZDB_THIEFTINYFACTOR, callback, NULL );
	     callbackAdded = true;
	 }
       }

       static void callback(const std::string& name, void*)
       {
	  if (name == StateDatabase::BZDB_OBESEFACTOR) {
	     styleFactors[1][0] = BZDB.eval(StateDatabase::BZDB_OBESEFACTOR);
	     styleFactors[1][1] = styleFactors[1][0];
	  }
	  else if (name == StateDatabase::BZDB_TINYFACTOR) {
	     styleFactors[2][0] = BZDB.eval(StateDatabase::BZDB_TINYFACTOR);
	     styleFactors[2][1] = styleFactors[2][0];
	  }
	  else if (name == StateDatabase::BZDB_THIEFTINYFACTOR) {
	     styleFactors[4][0] = BZDB.eval(StateDatabase::BZDB_THIEFTINYFACTOR);
	     styleFactors[4][1] = styleFactors[4][0];
	  }
       }

       //Modifiers for Normal, Obese. Tiny, Thin, Thief
       static GLfloat styleFactors[5][3];
       static bool callbackAdded;
};
bool TankFactors::callbackAdded = false;
GLfloat TankFactors::styleFactors[5][3] = {
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 0.001f, 1.0f },
			{ 1.0f, 1.0f, 1.0f }
		};

// parts: body, turret, barrel, left tread, right tread

const int		TankSceneNode::numLOD = 3;
int			TankSceneNode::maxLevel = numLOD;

TankSceneNode::TankSceneNode(const GLfloat pos[3], const GLfloat forward[3]) :
				useOverride(false),
				hidden(false),
				invisible(false),
				clip(false),
				style(TankRenderNode::Normal),
				lowRenderNode(this),
				medRenderNode(this),
				highRenderNode(this),
				shadowRenderNode(this)
{
  // setup style factors (BZDB isn't set up at global init time

  TankFactors(); // Install callbacks for styleFactors

			// prepare geometry
  move(pos, forward);
  baseRadius = 0.25f * (BZDB.eval(StateDatabase::BZDB_TANKLENGTH) * BZDB.eval(StateDatabase::BZDB_TANKLENGTH) +
			BZDB.eval(StateDatabase::BZDB_TANKWIDTH) * BZDB.eval(StateDatabase::BZDB_TANKWIDTH) +
			BZDBCache::tankHeight * BZDBCache::tankHeight);
  setRadius(baseRadius);

  color[3] = 1.0f;
  setColor(1.0f, 1.0f, 1.0f);
  setExplodeFraction(0.0f);

  shadowRenderNode.setShadow();
}

TankSceneNode::~TankSceneNode()
{
  // do nothing
}

void			TankSceneNode::setColor(
				GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
  color[0] = r;
  color[1] = g;
  color[2] = b;
  color[3] = a;
  transparent = (color[3] != 1.0f);
}

void			TankSceneNode::setColor(const GLfloat* rgba)
{
  color[0] = rgba[0];
  color[1] = rgba[1];
  color[2] = rgba[2];
  color[3] = rgba[3];
  transparent = (color[3] != 1.0f);
}

void			TankSceneNode::setMaterial(const OpenGLMaterial& mat)
{
  OpenGLGStateBuilder builder(gstate);
  builder.setMaterial(mat);
  gstate = builder.getState();
}

void			TankSceneNode::setTexture(const int texture)
{
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(texture);
  gstate = builder.getState();
}

void			TankSceneNode::move(const GLfloat pos[3],
					const GLfloat forward[3])
{
  azimuth = 180.0f / M_PI*atan2f(forward[1], forward[0]);
  elevation = -180.0f / M_PI*atan2f(forward[2], hypotf(forward[0],forward[1]));
  setCenter(pos);
}

void			TankSceneNode::notifyStyleChange()
{
  sort = !BZDBCache::zbuffer;
  OpenGLGStateBuilder builder(gstate);
  builder.enableTexture(BZDBCache::texture);
  builder.enableMaterial(BZDBCache::lighting);
  builder.setSmoothing(BZDBCache::smooth);
  if (BZDBCache::blend && transparent) {
    builder.setBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    builder.setStipple(1.0f);
  } else {
    builder.resetBlending();
    builder.setStipple(transparent ? 0.5f : 1.0f);
  }
  gstate = builder.getState();

  OpenGLGStateBuilder builder2(lightsGState);
  if (BZDBCache::smooth) {
    builder2.setBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    builder2.setSmoothing();
  } else {
    builder2.resetBlending();
    builder2.setSmoothing(false);
  }
  lightsGState = builder2.getState();
}

void			TankSceneNode::addRenderNodes(
				SceneRenderer& renderer)
{
  // don't draw hidden tanks.  this is mainly to avoid drawing player's
  // tank when player is using view from tank.  can't simply not include
  // player, though, cos then we wouldn't get the tank's shadow.
  if (hidden || invisible) return;

  // pick level of detail
  TankRenderNode* node;
  const GLfloat* sphere = getSphere();
  const ViewFrustum& view = renderer.getViewFrustum();
  const float size = sphere[3] * view.getAreaFactor() /
					getDistance(view.getEye());
  if (maxLevel == -1)
    node = &highRenderNode;
  else if (maxLevel > 2 && size > 55.0f)
    node = &highRenderNode;
  else if (maxLevel > 1 && size > 25.0f)
    node = &medRenderNode;
  else node = &lowRenderNode;

  // if drawing in sorted order then decide which order
{'fraction_non_alphanumeric': 0.13851459736926533, 'fraction_numerical': 0.02582611485402631, 'mean_word_length': 3.9876, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3805712', 'n_tokens_mistral': 4984, 'n_tokens_neox': 4627, 'n_words': 995}