<commit_before>//===-- lib/Codegen/MachineRegisterInfo.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the MachineRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI)
  : TRI(&TRI), IsSSA(true), TracksLiveness(true) {
  VRegInfo.reserve(256);
  RegAllocHints.reserve(256);
  UsedRegUnits.resize(TRI.getNumRegUnits());
  UsedPhysRegMask.resize(TRI.getNumRegs());

  // Create the physreg use/def lists.
  PhysRegUseDefLists = new MachineOperand*[TRI.getNumRegs()];
  memset(PhysRegUseDefLists, 0, sizeof(MachineOperand*)*TRI.getNumRegs());
}

MachineRegisterInfo::~MachineRegisterInfo() {
  delete [] PhysRegUseDefLists;
}

/// setRegClass - Set the register class of the specified virtual register.
///
void
MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) {
  VRegInfo[Reg].first = RC;
}

const TargetRegisterClass *
MachineRegisterInfo::constrainRegClass(unsigned Reg,
                                       const TargetRegisterClass *RC,
                                       unsigned MinNumRegs) {
  const TargetRegisterClass *OldRC = getRegClass(Reg);
  if (OldRC == RC)
    return RC;
  const TargetRegisterClass *NewRC = TRI->getCommonSubClass(OldRC, RC);
  if (!NewRC || NewRC == OldRC)
    return NewRC;
  if (NewRC->getNumRegs() < MinNumRegs)
    return 0;
  setRegClass(Reg, NewRC);
  return NewRC;
}

bool
MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) {
  const TargetInstrInfo *TII = TM.getInstrInfo();
  const TargetRegisterClass *OldRC = getRegClass(Reg);
  const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC);

  // Stop early if there is no room to grow.
  if (NewRC == OldRC)
    return false;

  // Accumulate constraints from all uses.
  for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E;
       ++I) {
    const TargetRegisterClass *OpRC =
      I->getRegClassConstraint(I.getOperandNo(), TII, TRI);
    if (unsigned SubIdx = I.getOperand().getSubReg()) {
      if (OpRC)
        NewRC = TRI->getMatchingSuperRegClass(NewRC, OpRC, SubIdx);
      else
        NewRC = TRI->getSubClassWithSubReg(NewRC, SubIdx);
    } else if (OpRC)
      NewRC = TRI->getCommonSubClass(NewRC, OpRC);
    if (!NewRC || NewRC == OldRC)
      return false;
  }
  setRegClass(Reg, NewRC);
  return true;
}

/// createVirtualRegister - Create and return a new virtual register in the
/// function with the specified register class.
///
unsigned
MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){
  assert(RegClass && "Cannot create register without RegClass!");
  assert(RegClass->isAllocatable() &&
         "Virtual register RegClass must be allocatable.");

  // New virtual register number.
  unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs());
  VRegInfo.grow(Reg);
  VRegInfo[Reg].first = RegClass;
  RegAllocHints.grow(Reg);
  return Reg;
}

/// clearVirtRegs - Remove all virtual registers (after physreg assignment).
void MachineRegisterInfo::clearVirtRegs() {
#ifndef NDEBUG
  for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i)
    assert(VRegInfo[TargetRegisterInfo::index2VirtReg(i)].second == 0 &&
           "Vreg use list non-empty still?");
#endif
  VRegInfo.clear();
}

/// Add MO to the linked list of operands for its register.
void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) {
  assert(!MO->isOnRegUseList() && "Already on list");
  MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
  MachineOperand *const Head = HeadRef;

  // Head points to the first list element.
  // Next is NULL on the last list element.
  // Prev pointers are circular, so Head->Prev == Last.

  // Head is NULL for an empty list.
  if (!Head) {
    MO->Contents.Reg.Prev = MO;
    MO->Contents.Reg.Next = 0;
    HeadRef = MO;
    return;
  }
  assert(MO->getReg() == Head->getReg() && "Different regs on the same list!");

  // Insert MO between Last and Head in the circular Prev chain.
  MachineOperand *Last = Head->Contents.Reg.Prev;
  assert(Last && "Inconsistent use list");
  assert(MO->getReg() == Last->getReg() && "Different regs on the same list!");
  Head->Contents.Reg.Prev = MO;
  MO->Contents.Reg.Prev = Last;

  // Def operands always precede uses. This allows def_iterator to stop early.
  // Insert def operands at the front, and use operands at the back.
  if (MO->isDef()) {
    // Insert def at the front.
    MO->Contents.Reg.Next = Head;
    HeadRef = MO;
  } else {
    // Insert use at the end.
    MO->Contents.Reg.Next = 0;
    Last->Contents.Reg.Next = MO;
  }
}

/// Remove MO from its use-def list.
void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) {
  assert(MO->isOnRegUseList() && "Operand not on use list");
  MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
  MachineOperand *const Head = HeadRef;
  assert(Head && "List already empty");

  // Unlink this from the doubly linked list of operands.
  MachineOperand *Next = MO->Contents.Reg.Next;
  MachineOperand *Prev = MO->Contents.Reg.Prev;

  // Prev links are circular, next link is NULL instead of looping back to Head.
  if (MO == Head)
    HeadRef = Next;
  else
    Prev->Contents.Reg.Next = Next;

  (Next ? Next : Head)->Contents.Reg.Prev = Prev;

  MO->Contents.Reg.Prev = 0;
  MO->Contents.Reg.Next = 0;
}

/// Move NumOps operands from Src to Dst, updating use-def lists as needed.
///
/// The Dst range is assumed to be uninitialized memory. (Or it may contain
/// operands that won't be destroyed, which is OK because the MO destructor is
/// trivial anyway).
///
/// The Src and Dst ranges may overlap.
void MachineRegisterInfo::moveOperands(MachineOperand *Dst,
                                       MachineOperand *Src,
                                       unsigned NumOps) {
  assert(Src != Dst && NumOps && "Noop moveOperands");

  // Copy backwards if Dst is within the Src range.
  int Stride = 1;
  if (Dst >= Src && Dst < Src + NumOps) {
    Stride = -1;
    Dst += NumOps - 1;
    Src += NumOps - 1;
  }

  // Copy one operand at a time.
  do {
    new (Dst) MachineOperand(*Src);

    // Dst takes Src's place in the use-def chain.
    if (Src->isReg()) {
      MachineOperand *&Head = getRegUseDefListHead(Src->getReg());
      MachineOperand *Prev = Src->Contents.Reg.Prev;
      MachineOperand *Next = Src->Contents.Reg.Next;
      assert(Head && "List empty, but operand is chained");
      assert(Prev && "Operand was not on use-def list");

      // Prev links are circular, next link is NULL instead of looping back to
      // Head.
      if (Src == Head)
        Head = Dst;
      else
        Prev->Contents.Reg.Next = Dst;

      // Update Prev pointer. This also works when Src was pointing to itself
      // in a 1-element list. In that case Head == Dst.
      (Next ? Next : Head)->Contents.Reg.Prev = Dst;
    }

    Dst += Stride;
    Src += Stride;
  } while (--NumOps);
}

/// replaceRegWith - Replace all instances of FromReg with ToReg in the
/// machine function.  This is like llvm-level X->replaceAllUsesWith(Y),
/// except that it also changes any definitions of the register as well.
void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) {
  assert(FromReg != ToReg && "Cannot replace a reg with itself");

  // TODO: This could be more efficient by bulk changing the operands.
  for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) {
    MachineOperand &O = I.getOperand();
    ++I;
    O.setReg(ToReg);
  }
}

/// getVRegDef - Return the machine instr that defines the specified virtual
/// register or null if none is found.  This assumes that the code is in SSA
/// form, so there should only be one definition.
MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const {
  // Since we are in SSA form, we can use the first definition.
  def_iterator I = def_begin(Reg);
  assert((I.atEnd() || llvm::next(I) == def_end()) &&
         "getVRegDef assumes a single definition or no definition");
  return !I.atEnd() ? &*I : 0;
}

/// getUniqueVRegDef - Return the unique machine instr that defines the
/// specified virtual register or null if none is found.  If there are
/// multiple definitions or no definition, return null.
MachineInstr *MachineRegisterInfo::getUniqueVRegDef(unsigned Reg) const {
  if (def_empty(Reg)) return 0;
  def_iterator I = def_begin(Reg);
  if (llvm::next(I) != def_end())
    return 0;
  return &*I;
}

bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const {
  use_nodbg_iterator UI = use_nodbg_begin(RegNo);
  if (UI == use_nodbg_end())
    return false;
  return ++UI == use_nodbg_end();
}

/// clearKillFlags - Iterate over all the uses of the given register and
/// clear the kill flag from the MachineOperand. This function is used by
/// optimization passes which extend register lifetimes and need only
/// preserve conservative kill flag information.
void MachineRegisterInfo::clearKillFlags(unsigned Reg) const {
  for (use_iterator UI = use_begin(Reg), UE = use_end(); UI != UE; ++UI)
    UI.getOperand().setIsKill(false);
}

bool MachineRegisterInfo::isLiveIn(unsigned Reg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->first == Reg || I->second == Reg)
      return true;
  return false;
}

/// getLiveInPhysReg - If VReg is a live-in virtual register, return the
/// corresponding live-in physical register.
unsigned MachineRegisterInfo::getLiveInPhysReg(unsigned VReg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->second == VReg)
      return I->first;
  return 0;
}

/// getLiveInVirtReg - If PReg is a live-in physical register, return the
/// corresponding live-in physical register.
unsigned MachineRegisterInfo::getLiveInVirtReg(unsigned PReg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->first == PReg)
      return I->second;
  return 0;
}

/// EmitLiveInCopies - Emit copies to initialize livein virtual registers
/// into the given entry block.
void
MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB,
                                      const TargetRegisterInfo &TRI,
                                      const TargetInstrInfo &TII) {
  // Emit the copies into the top of the block.
  for (unsigned i = 0, e = LiveIns.size(); i != e; ++i)
    if (LiveIns[i].second) {
      if (use_empty(LiveIns[i].second)) {
        // The livein has no uses. Drop it.
        //
        // It would be preferable to have isel avoid creating live-in
        // records for unused arguments in the first place, but it's
        // complicated by the debug info code for arguments.
        LiveIns.erase(LiveIns.begin() + i);
        --i; --e;
      } else {
        // Emit a copy.
        BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(),
                TII.get(TargetOpcode::COPY), LiveIns[i].second)
          .addReg(LiveIns[i].first);

        // Add the register to the entry block live-in set.
        EntryMBB->addLiveIn(LiveIns[i].first);
      }
    } else {
      // Add the register to the entry block live-in set.
      EntryMBB->addLiveIn(LiveIns[i].first);
    }
}

#ifndef NDEBUG
void MachineRegisterInfo::dumpUses(unsigned Reg) const {
  for (use_iterator I = use_begin(Reg), E = use_end(); I != E; ++I)
    I.getOperand().getParent()->dump();
}
#endif

void MachineRegisterInfo::freezeReservedRegs(const MachineFunction &MF) {
  ReservedRegs = TRI->getReservedRegs(MF);
  assert(ReservedRegs.size() == TRI->getNumRegs() &&
         "Invalid ReservedRegs vector from target");
}

bool MachineRegisterInfo::isConstantPhysReg(unsigned PhysReg,
                                            const MachineFunction &MF) const {
  assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));

  // Check if any overlapping register is modified, or allocatable so it may be
  // used later.
  for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI)
    if (!def_empty(*AI) || isAllocatable(*AI))
      return false;
  return true;
}
<commit_msg>Check register classes also when changing them.<commit_after>//===-- lib/Codegen/MachineRegisterInfo.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the MachineRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI)
  : TRI(&TRI), IsSSA(true), TracksLiveness(true) {
  VRegInfo.reserve(256);
  RegAllocHints.reserve(256);
  UsedRegUnits.resize(TRI.getNumRegUnits());
  UsedPhysRegMask.resize(TRI.getNumRegs());

  // Create the physreg use/def lists.
  PhysRegUseDefLists = new MachineOperand*[TRI.getNumRegs()];
  memset(PhysRegUseDefLists, 0, sizeof(MachineOperand*)*TRI.getNumRegs());
}

MachineRegisterInfo::~MachineRegisterInfo() {
  delete [] PhysRegUseDefLists;
}

/// setRegClass - Set the register class of the specified virtual register.
///
void
MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) {
  assert(RC && RC->isAllocatable() && "Invalid RC for virtual register");
  VRegInfo[Reg].first = RC;
}

const TargetRegisterClass *
MachineRegisterInfo::constrainRegClass(unsigned Reg,
                                       const TargetRegisterClass *RC,
                                       unsigned MinNumRegs) {
  const TargetRegisterClass *OldRC = getRegClass(Reg);
  if (OldRC == RC)
    return RC;
  const TargetRegisterClass *NewRC = TRI->getCommonSubClass(OldRC, RC);
  if (!NewRC || NewRC == OldRC)
    return NewRC;
  if (NewRC->getNumRegs() < MinNumRegs)
    return 0;
  setRegClass(Reg, NewRC);
  return NewRC;
}

bool
MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) {
  const TargetInstrInfo *TII = TM.getInstrInfo();
  const TargetRegisterClass *OldRC = getRegClass(Reg);
  const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC);

  // Stop early if there is no room to grow.
  if (NewRC == OldRC)
    return false;

  // Accumulate constraints from all uses.
  for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E;
       ++I) {
    const TargetRegisterClass *OpRC =
      I->getRegClassConstraint(I.getOperandNo(), TII, TRI);
    if (unsigned SubIdx = I.getOperand().getSubReg()) {
      if (OpRC)
        NewRC = TRI->getMatchingSuperRegClass(NewRC, OpRC, SubIdx);
      else
        NewRC = TRI->getSubClassWithSubReg(NewRC, SubIdx);
    } else if (OpRC)
      NewRC = TRI->getCommonSubClass(NewRC, OpRC);
    if (!NewRC || NewRC == OldRC)
      return false;
  }
  setRegClass(Reg, NewRC);
  return true;
}

/// createVirtualRegister - Create and return a new virtual register in the
/// function with the specified register class.
///
unsigned
MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){
  assert(RegClass && "Cannot create register without RegClass!");
  assert(RegClass->isAllocatable() &&
         "Virtual register RegClass must be allocatable.");

  // New virtual register number.
  unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs());
  VRegInfo.grow(Reg);
  VRegInfo[Reg].first = RegClass;
  RegAllocHints.grow(Reg);
  return Reg;
}

/// clearVirtRegs - Remove all virtual registers (after physreg assignment).
void MachineRegisterInfo::clearVirtRegs() {
#ifndef NDEBUG
  for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i)
    assert(VRegInfo[TargetRegisterInfo::index2VirtReg(i)].second == 0 &&
           "Vreg use list non-empty still?");
#endif
  VRegInfo.clear();
}

/// Add MO to the linked list of operands for its register.
void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) {
  assert(!MO->isOnRegUseList() && "Already on list");
  MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
  MachineOperand *const Head = HeadRef;

  // Head points to the first list element.
  // Next is NULL on the last list element.
  // Prev pointers are circular, so Head->Prev == Last.

  // Head is NULL for an empty list.
  if (!Head) {
    MO->Contents.Reg.Prev = MO;
    MO->Contents.Reg.Next = 0;
    HeadRef = MO;
    return;
  }
  assert(MO->getReg() == Head->getReg() && "Different regs on the same list!");

  // Insert MO between Last and Head in the circular Prev chain.
  MachineOperand *Last = Head->Contents.Reg.Prev;
  assert(Last && "Inconsistent use list");
  assert(MO->getReg() == Last->getReg() && "Different regs on the same list!");
  Head->Contents.Reg.Prev = MO;
  MO->Contents.Reg.Prev = Last;

  // Def operands always precede uses. This allows def_iterator to stop early.
  // Insert def operands at the front, and use operands at the back.
  if (MO->isDef()) {
    // Insert def at the front.
    MO->Contents.Reg.Next = Head;
    HeadRef = MO;
  } else {
    // Insert use at the end.
    MO->Contents.Reg.Next = 0;
    Last->Contents.Reg.Next = MO;
  }
}

/// Remove MO from its use-def list.
void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) {
  assert(MO->isOnRegUseList() && "Operand not on use list");
  MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
  MachineOperand *const Head = HeadRef;
  assert(Head && "List already empty");

  // Unlink this from the doubly linked list of operands.
  MachineOperand *Next = MO->Contents.Reg.Next;
  MachineOperand *Prev = MO->Contents.Reg.Prev;

  // Prev links are circular, next link is NULL instead of looping back to Head.
  if (MO == Head)
    HeadRef = Next;
  else
    Prev->Contents.Reg.Next = Next;

  (Next ? Next : Head)->Contents.Reg.Prev = Prev;

  MO->Contents.Reg.Prev = 0;
  MO->Contents.Reg.Next = 0;
}

/// Move NumOps operands from Src to Dst, updating use-def lists as needed.
///
/// The Dst range is assumed to be uninitialized memory. (Or it may contain
/// operands that won't be destroyed, which is OK because the MO destructor is
/// trivial anyway).
///
/// The Src and Dst ranges may overlap.
void MachineRegisterInfo::moveOperands(MachineOperand *Dst,
                                       MachineOperand *Src,
                                       unsigned NumOps) {
  assert(Src != Dst && NumOps && "Noop moveOperands");

  // Copy backwards if Dst is within the Src range.
  int Stride = 1;
  if (Dst >= Src && Dst < Src + NumOps) {
    Stride = -1;
    Dst += NumOps - 1;
    Src += NumOps - 1;
  }

  // Copy one operand at a time.
  do {
    new (Dst) MachineOperand(*Src);

    // Dst takes Src's place in the use-def chain.
    if (Src->isReg()) {
      MachineOperand *&Head = getRegUseDefListHead(Src->getReg());
      MachineOperand *Prev = Src->Contents.Reg.Prev;
      MachineOperand *Next = Src->Contents.Reg.Next;
      assert(Head && "List empty, but operand is chained");
      assert(Prev && "Operand was not on use-def list");

      // Prev links are circular, next link is NULL instead of looping back to
      // Head.
      if (Src == Head)
        Head = Dst;
      else
        Prev->Contents.Reg.Next = Dst;

      // Update Prev pointer. This also works when Src was pointing to itself
      // in a 1-element list. In that case Head == Dst.
      (Next ? Next : Head)->Contents.Reg.Prev = Dst;
    }

    Dst += Stride;
    Src += Stride;
  } while (--NumOps);
}

/// replaceRegWith - Replace all instances of FromReg with ToReg in the
/// machine function.  This is like llvm-level X->replaceAllUsesWith(Y),
/// except that it also changes any definitions of the register as well.
void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) {
  assert(FromReg != ToReg && "Cannot replace a reg with itself");

  // TODO: This could be more efficient by bulk changing the operands.
  for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) {
    MachineOperand &O = I.getOperand();
    ++I;
    O.setReg(ToReg);
  }
}

/// getVRegDef - Return the machine instr that defines the specified virtual
/// register or null if none is found.  This assumes that the code is in SSA
/// form, so there should only be one definition.
MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const {
  // Since we are in SSA form, we can use the first definition.
  def_iterator I = def_begin(Reg);
  assert((I.atEnd() || llvm::next(I) == def_end()) &&
         "getVRegDef assumes a single definition or no definition");
  return !I.atEnd() ? &*I : 0;
}

/// getUniqueVRegDef - Return the unique machine instr that defines the
/// specified virtual register or null if none is found.  If there are
/// multiple definitions or no definition, return null.
MachineInstr *MachineRegisterInfo::getUniqueVRegDef(unsigned Reg) const {
  if (def_empty(Reg)) return 0;
  def_iterator I = def_begin(Reg);
  if (llvm::next(I) != def_end())
    return 0;
  return &*I;
}

bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const {
  use_nodbg_iterator UI = use_nodbg_begin(RegNo);
  if (UI == use_nodbg_end())
    return false;
  return ++UI == use_nodbg_end();
}

/// clearKillFlags - Iterate over all the uses of the given register and
/// clear the kill flag from the MachineOperand. This function is used by
/// optimization passes which extend register lifetimes and need only
/// preserve conservative kill flag information.
void MachineRegisterInfo::clearKillFlags(unsigned Reg) const {
  for (use_iterator UI = use_begin(Reg), UE = use_end(); UI != UE; ++UI)
    UI.getOperand().setIsKill(false);
}

bool MachineRegisterInfo::isLiveIn(unsigned Reg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->first == Reg || I->second == Reg)
      return true;
  return false;
}

/// getLiveInPhysReg - If VReg is a live-in virtual register, return the
/// corresponding live-in physical register.
unsigned MachineRegisterInfo::getLiveInPhysReg(unsigned VReg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->second == VReg)
      return I->first;
  return 0;
}

/// getLiveInVirtReg - If PReg is a live-in physical register, return the
/// corresponding live-in physical register.
unsigned MachineRegisterInfo::getLiveInVirtReg(unsigned PReg) const {
  for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
    if (I->first == PReg)
      return I->second;
  return 0;
}

/// EmitLiveInCopies - Emit copies to initialize livein virtual registers
/// into the given entry block.
void
MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB,
                                      const TargetRegisterInfo &TRI,
                                      const TargetInstrInfo &TII) {
  // Emit the copies into the top of the block.
  for (unsigned i = 0, e = LiveIns.size(); i != e; ++i)
    if (LiveIns[i].second) {
      if (use_empty(LiveIns[i].second)) {
        // The livein has no uses. Drop it.
        //
        // It would be preferable to have isel avoid creating live-in
        // records for unused arguments in the first place, but it's
        // complicated by the debug info code for arguments.
        LiveIns.erase(LiveIns.begin() + i);
        --i; --e;
      } else {
        // Emit a copy.
        BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(),
                TII.get(TargetOpcode::COPY), LiveIns[i].second)
          .addReg(LiveIns[i].first);

        // Add the register to the entry block live-in set.
        EntryMBB->addLiveIn(LiveIns[i].first);
      }
    } else {
      // Add the register to the entry block live-in set.
      EntryMBB->addLiveIn(LiveIns[i].first);
    }
}

#ifndef NDEBUG
void MachineRegisterInfo::dumpUses(unsigned Reg) const {
  for (use_iterator I = use_begin(Reg), E = use_end(); I != E; ++I)
    I.getOperand().getParent()->dump();
}
#endif

void MachineRegisterInfo::freezeReservedRegs(const MachineFunction &MF) {
  ReservedRegs = TRI->getReservedRegs(MF);
  assert(ReservedRegs.size() == TRI->getNumRegs() &&
         "Invalid ReservedRegs vector from target");
}

bool MachineRegisterInfo::isConstantPhysReg(unsigned PhysReg,
                                            const MachineFunction &MF) const {
  assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));

  // Check if any overlapping register is modified, or allocatable so it may be
  // used later.
  for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI)
    if (!def_empty(*AI) || isAllocatable(*AI))
      return false;
  return true;
}
<|endoftext|>


<commit_before>/* mockturtle: C++ logic network library
 * Copyright (C) 2018  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/*!
  \file window_view.hpp
  \brief Implements an isolated view on a window in a network

  \author Heinz Riener
*/

#pragma once

#include <algorithm>
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <set>
#include <cassert>

#include "../traits.hpp"
#include "../networks/detail/foreach.hpp"
#include "../views/parents_view.hpp"
#include "immutable_view.hpp"

namespace mockturtle
{

/*! \brief Implements an isolated view on a window in a network.
 *
 */
template<typename Ntk>
class window_view : public immutable_view<Ntk>
{
public:
  using storage = typename Ntk::storage;
  using node = typename Ntk::node;
  using signal = typename Ntk::signal;

public:
  explicit window_view( Ntk const& ntk, const std::vector<node>& leaves, const std::vector<node>& pivots, bool auto_extend = true )
    : immutable_view<Ntk>( ntk )
  {
    static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
    static_assert( has_set_visited_v<Ntk>, "Ntk does not implement the set_visited method" );
    static_assert( has_visited_v<Ntk>, "Ntk does not implement the visited method" );
    static_assert( has_get_node_v<Ntk>, "Ntk does not implement the get_node method" );
    static_assert( has_get_constant_v<Ntk>, "Ntk does not implement the get_constant method" );
    static_assert( has_is_constant_v<Ntk>, "Ntk does not implement the is_constant method" );
    static_assert( has_make_signal_v<Ntk>, "Ntk does not implement the make_signal method" );
    static_assert( has_foreach_parent_v<Ntk>, "Ntk does not implement the foreach_parent method" );

    /* constants */
    add_node( this->get_node( this->get_constant( false ) ) );
    this->set_visited( this->get_node( this->get_constant( false ) ), 1 );
    if ( this->get_node( this->get_constant( true ) ) != this->get_node( this->get_constant( false ) ) )
    {
      add_node( this->get_node( this->get_constant( true ) ) );
      this->set_visited( this->get_node( this->get_constant( true ) ), 1 );
      ++_num_constants;
    }

    /* primary inputs */
    for ( auto const& leaf : leaves )
    {
      if ( this->visited( leaf ) == 1 )
        continue;

      add_node( leaf );
      this->set_visited( leaf, 1 );
      ++_num_leaves;
    }

    for ( auto const& p : pivots )
    {
      traverse( p );
    }

    if ( auto_extend )
    {
      extend( ntk );
    }

    add_roots( ntk );

    /* restore visited */
    for ( auto const& n : _nodes )
    {
      this->set_visited( n, 0 );
    }
  }

  inline auto size() const { return _nodes.size(); }
  inline auto num_pis() const { return _num_leaves; }
  inline auto num_pos() const { return _roots.size(); }
  inline auto num_gates() const { return _nodes.size() - _num_leaves - _num_constants; }

  inline auto node_to_index( const node& n ) const { return _node_to_index.at( n ); }
  inline auto index_to_node( uint32_t index ) const { return _nodes[index]; }

  inline bool is_pi( node const& pi ) const
  {
    const auto beg = _nodes.begin() + _num_constants;
    return std::find( beg, beg + _num_leaves, pi ) != beg + _num_leaves;
  }

  inline bool is_po( node const& po ) const
  {
    return std::find( _roots.begin(), _roots.end(), po ) != _roots.end();
  }

  template<typename Fn>
  void foreach_pi( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin() + _num_constants, _nodes.begin() + _num_constants + _num_leaves, fn );
  }

  template<typename Fn>
  void foreach_po( Fn&& fn ) const
  {
    detail::foreach_element( _roots.begin(), _roots.end(), fn );
  }

  template<typename Fn>
  void foreach_node( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin(), _nodes.end(), fn );
  }

  template<typename Fn>
  void foreach_gate( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin() + _num_constants + _num_leaves, _nodes.end(), fn );
  }

  uint32_t fanout_size( node const& n ) const
  {
    return _fanout_size.at( node_to_index(n) );
  }

private:
  void add_node( node const& n )
  {
    _node_to_index[n] = _nodes.size();
    _nodes.push_back( n );

    auto fanout_counter = 0;
    this->foreach_fanin( n, [&]( const auto& f ) {
        if ( std::find( _nodes.begin(), _nodes.end(), this->get_node( f ) ) != _nodes.end() )
        {
          fanout_counter++;
        }
      });
    _fanout_size.push_back( fanout_counter );
  }

  void traverse( node const& n )
  {
    if ( this->visited( n ) == 1 )
      return;

    this->foreach_fanin( n, [&]( const auto& f ) {
      traverse( this->get_node( f ) );
    } );

    add_node( n );
    this->set_visited( n, 1 );
  }

  void extend( Ntk const& ntk )
  {
    std::set<node> new_nodes;
    do
    {
      new_nodes.clear();
      for ( const auto& n : _nodes )
      {
        ntk.foreach_parent( n, [&]( auto const& p ){
            /* skip node if it is already in _nodes */
            if ( std::find( _nodes.begin(), _nodes.end(), p ) != _nodes.end() ) return;

            auto all_children_in_nodes = true;
            ntk.foreach_fanin( p, [&]( auto const& s ){
                auto const& child = ntk.get_node( s );
                if ( std::find( _nodes.begin(), _nodes.end(), child ) == _nodes.end() )
                {
                  all_children_in_nodes = false;
                  return false;
                }
                return true;
              });

            if ( all_children_in_nodes )
            {
              assert( p != 0 );
              assert( !is_pi( p ) );
              new_nodes.insert( p );
            }
          });
      }

      for ( const auto& n : new_nodes )
      {
        add_node( n );
      }
    } while ( !new_nodes.empty() );
  }

  void add_roots( Ntk const& ntk )
  {
    /* compute po nodes */
    std::vector<node> pos;
    ntk.foreach_po( [&]( auto const& s ){
        pos.push_back( ntk.get_node( s ) );
      });

    /* compute window outputs */
    for ( const auto& n : _nodes )
    {
      // if ( ntk.is_constant( n ) || ntk.is_pi( n ) ) continue;

      if ( std::find( pos.begin(), pos.end(), n ) != pos.end() )
      {
        _roots.push_back( n );
        continue;
      }

      ntk.foreach_parent( n, [&]( auto const& p ){
          if ( std::find( _nodes.begin(), _nodes.end(), p ) == _nodes.end() )
          {
            if ( std::find( _roots.begin(), _roots.end(), n ) == _roots.end() )
            {
              _roots.push_back( n );
              return false;
            }
          }
          return true;
      });
    }
  }

public:
  unsigned _num_constants{1};
  unsigned _num_leaves{0};
  std::vector<node> _nodes;
  std::unordered_map<node, uint32_t> _node_to_index;
  std::vector<node> _roots;
  std::vector<unsigned> _fanout_size;
};

} /* namespace mockturtle */
<commit_msg>window_view.<commit_after>/* mockturtle: C++ logic network library
 * Copyright (C) 2018  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/*!
  \file window_view.hpp
  \brief Implements an isolated view on a window in a network

  \author Heinz Riener
*/

#pragma once

#include <algorithm>
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <set>
#include <cassert>

#include "../traits.hpp"
#include "../networks/detail/foreach.hpp"
#include "../views/parents_view.hpp"
#include "immutable_view.hpp"

namespace mockturtle
{

/*! \brief Implements an isolated view on a window in a network.
 *
 */
template<typename Ntk>
class window_view : public immutable_view<Ntk>
{
public:
  using storage = typename Ntk::storage;
  using node = typename Ntk::node;
  using signal = typename Ntk::signal;

public:
  explicit window_view( Ntk const& ntk, const std::vector<node>& leaves, const std::vector<node>& pivots, bool auto_extend = true )
    : immutable_view<Ntk>( ntk )
  {
    static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
    static_assert( has_set_visited_v<Ntk>, "Ntk does not implement the set_visited method" );
    static_assert( has_visited_v<Ntk>, "Ntk does not implement the visited method" );
    static_assert( has_get_node_v<Ntk>, "Ntk does not implement the get_node method" );
    static_assert( has_get_constant_v<Ntk>, "Ntk does not implement the get_constant method" );
    static_assert( has_is_constant_v<Ntk>, "Ntk does not implement the is_constant method" );
    static_assert( has_make_signal_v<Ntk>, "Ntk does not implement the make_signal method" );
    static_assert( has_foreach_parent_v<Ntk>, "Ntk does not implement the foreach_parent method" );

    /* constants */
    add_node( this->get_node( this->get_constant( false ) ) );
    this->set_visited( this->get_node( this->get_constant( false ) ), 1 );
    if ( this->get_node( this->get_constant( true ) ) != this->get_node( this->get_constant( false ) ) )
    {
      add_node( this->get_node( this->get_constant( true ) ) );
      this->set_visited( this->get_node( this->get_constant( true ) ), 1 );
      ++_num_constants;
    }

    /* primary inputs */
    for ( auto const& leaf : leaves )
    {
      if ( this->visited( leaf ) == 1 )
        continue;

      add_node( leaf );
      this->set_visited( leaf, 1 );
      ++_num_leaves;
    }

    for ( auto const& p : pivots )
    {
      traverse( p );
    }

    if ( auto_extend )
    {
      extend( ntk );
    }

    add_roots( ntk );

    /* restore visited */
    for ( auto const& n : _nodes )
    {
      this->set_visited( n, 0 );
    }
  }

  inline auto size() const { return _nodes.size(); }
  inline auto num_pis() const { return _num_leaves; }
  inline auto num_pos() const { return _roots.size(); }
  inline auto num_gates() const { return _nodes.size() - _num_leaves - _num_constants; }

  inline auto node_to_index( const node& n ) const { return _node_to_index.at( n ); }
  inline auto index_to_node( uint32_t index ) const { return _nodes[index]; }

  inline bool is_pi( node const& pi ) const
  {
    const auto beg = _nodes.begin() + _num_constants;
    return std::find( beg, beg + _num_leaves, pi ) != beg + _num_leaves;
  }

  template<typename Fn>
  void foreach_pi( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin() + _num_constants, _nodes.begin() + _num_constants + _num_leaves, fn );
  }

  template<typename Fn>
  void foreach_po( Fn&& fn ) const
  {
    detail::foreach_element( _roots.begin(), _roots.end(), fn );
  }

  template<typename Fn>
  void foreach_node( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin(), _nodes.end(), fn );
  }

  template<typename Fn>
  void foreach_gate( Fn&& fn ) const
  {
    detail::foreach_element( _nodes.begin() + _num_constants + _num_leaves, _nodes.end(), fn );
  }

  uint32_t fanout_size( node const& n ) const
  {
    return _fanout_size.at( node_to_index(n) );
  }

private:
  void add_node( node const& n )
  {
    _node_to_index[n] = _nodes.size();
    _nodes.push_back( n );

    auto fanout_counter = 0;
    this->foreach_fanin( n, [&]( const auto& f ) {
        if ( std::find( _nodes.begin(), _nodes.end(), this->get_node( f ) ) != _nodes.end() )
        {
          fanout_counter++;
        }
      });
    _fanout_size.push_back( fanout_counter );
  }

  void traverse( node const& n )
  {
    if ( this->visited( n ) == 1 )
      return;

    this->foreach_fanin( n, [&]( const auto& f ) {
      traverse( this->get_node( f ) );
    } );

    add_node( n );
    this->set_visited( n, 1 );
  }

  void extend( Ntk const& ntk )
  {
    std::set<node> new_nodes;
    do
    {
      new_nodes.clear();
      for ( const auto& n : _nodes )
      {
        ntk.foreach_parent( n, [&]( auto const& p ){
            /* skip node if it is already in _nodes */
            if ( std::find( _nodes.begin(), _nodes.end(), p ) != _nodes.end() ) return;

            auto all_children_in_nodes = true;
            ntk.foreach_fanin( p, [&]( auto const& s ){
                auto const& child = ntk.get_node( s );
                if ( std::find( _nodes.begin(), _nodes.end(), child ) == _nodes.end() )
                {
                  all_children_in_nodes = false;
                  return false;
                }
                return true;
              });

            if ( all_children_in_nodes )
            {
              assert( p != 0 );
              assert( !is_pi( p ) );
              new_nodes.insert( p );
            }
          });
      }

      for ( const auto& n : new_nodes )
      {
        add_node( n );
      }
    } while ( !new_nodes.empty() );
  }

  void add_roots( Ntk const& ntk )
  {
    /* compute po nodes */
    std::vector<node> pos;
    ntk.foreach_po( [&]( auto const& s ){
        pos.push_back( ntk.get_node( s ) );
      });

    /* compute window outputs */
    for ( const auto& n : _nodes )
    {
      // if ( ntk.is_constant( n ) || ntk.is_pi( n ) ) continue;

      if ( std::find( pos.begin(), pos.end(), n ) != pos.end() )
      {
        auto s = this->make_signal( n );
        if ( std::find( _roots.begin(), _roots.end(), s ) == _roots.end() )
        {
          _roots.push_back( s );
        }
        continue;
      }

      ntk.foreach_parent( n, [&]( auto const& p ){
          if ( std::find( _nodes.begin(), _nodes.end(), p ) == _nodes.end() )
          {
            auto s = this->make_signal( n );
            if ( std::find( _roots.begin(), _roots.end(), s ) == _roots.end() )
            {
              _roots.push_back( s );
              return false;
            }
          }
          return true;
      });
    }
  }

public:
  unsigned _num_constants{1};
  unsigned _num_leaves{0};
  std::vector<node> _nodes;
  std::unordered_map<node, uint32_t> _node_to_index;
  std::vector<signal> _roots;
  std::vector<unsigned> _fanout_size;
};

} /* namespace mockturtle */
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "cnglob.h"
#include "strpak.h"

TEST(strpak, compare_case_insensitive_string)
{
	// Set up strings to compare
	const char* helloUpperCase = "HELLO";
	const char* helloLowerCase = "hello";
	const char* helloWrong = "H3llo";
	const char* longStringUpperCase = "This IS a LONG string.";
	const char* longStringLowerCase = "this is a long string ";
	const char* longStringWrongCase = "this is a wrong string.";

	// Test _stricmp
	EXPECT_EQ( _stricmp(helloUpperCase, helloLowerCase), 0);
	EXPECT_EQ( _stricmp(helloUpperCase, helloWrong), 50);
	EXPECT_EQ(_stricmp(longStringUpperCase,longStringLowerCase), 14);
	EXPECT_EQ( _stricmp(longStringUpperCase, longStringWrongCase), -11);

	// Test _strnicmp
	EXPECT_EQ( _strnicmp(helloUpperCase, helloLowerCase, 5), 0);
	EXPECT_EQ( _strnicmp(helloUpperCase, helloWrong, 4), 1);
	EXPECT_EQ( _strnicmp(helloUpperCase, helloWrong, 1), 0);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringLowerCase, 22), 1);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringLowerCase, 20), 0);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringWrongCase, 22), -1);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringWrongCase, 10), 0);
}
<commit_msg>Fix spacing.<commit_after>#include "gtest/gtest.h"

#include "cnglob.h"
#include "strpak.h"

TEST(strpak, compare_case_insensitive_string)
{
	// Set up strings to compare
	const char* helloUpperCase = "HELLO";
	const char* helloLowerCase = "hello";
	const char* helloWrong = "H3llo";
	const char* longStringUpperCase = "This IS a LONG string.";
	const char* longStringLowerCase = "this is a long string ";
	const char* longStringWrongCase = "this is a wrong string.";

	// Test _stricmp
	EXPECT_EQ( _stricmp(helloUpperCase, helloLowerCase), 0);
	EXPECT_EQ( _stricmp(helloUpperCase, helloWrong), 50);
	EXPECT_EQ( _stricmp(longStringUpperCase,longStringLowerCase), 14);
	EXPECT_EQ( _stricmp(longStringUpperCase, longStringWrongCase), -11);

	// Test _strnicmp
	EXPECT_EQ( _strnicmp(helloUpperCase, helloLowerCase, 5), 0);
	EXPECT_EQ( _strnicmp(helloUpperCase, helloWrong, 4), 1);
	EXPECT_EQ( _strnicmp(helloUpperCase, helloWrong, 1), 0);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringLowerCase, 22), 1);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringLowerCase, 20), 0);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringWrongCase, 22), -1);
	EXPECT_EQ( _strnicmp(longStringUpperCase, longStringWrongCase, 10), 0);
}
<|endoftext|>


<commit_before>#pragma once

#include "sani/core/profiling/impl/profiler_impl.hpp"
#include "sani/core/profiling/profiler_module.hpp"
#include "sani/core/utils/string_utils.hpp"

#include <list>

#define BEGIN_PROFILING		sani::profiler::__privns__::startProfiling(typeid(this).name(), __FUNCTION__)
#define END_PROFILING		sani::profiler::__privns__::endProfiling(typeid(this).name(), __FUNCTION__)

#define START_PROFILER		sani::profiler::__privns__::startProfiler(typeid(this).name(), __FUNCTION__)
#define STOP_PROFILER		sani::profiler::__privns__::stopProfiler(typeid(this).name(), __FUNCTION__)

#define PROFILER_MAKE_ROOT	sani::profiler::__privns__::makeRoot(typeid(this).name(), __FUNCTION__)

namespace sani {

	namespace profiler {

		namespace {

			ProfilerImpl impl;
		}

		/*
			TODO: should these be "hidden" or not?..
		*/

		namespace __privns__ {

			void startProfiler(const String& module, const String& function);
			void stopProfiler(const String& module, const String& function);

			void startProfiling(const String& module, const String& function);
			void endProfiling(const String& module, const String& function);

			void makeRoot(const String& module, const String& function);
		}

		float32 rootElapsedMicroseconds();
		const String& rootFunction();
		const String& rootModule();

		const Modules& modules();
	}
}<commit_msg>add todo to profiler about the models<commit_after>#pragma once

#include "sani/core/profiling/impl/profiler_impl.hpp"
#include "sani/core/profiling/profiler_module.hpp"
#include "sani/core/utils/string_utils.hpp"

#include <list>

#define BEGIN_PROFILING		sani::profiler::__privns__::startProfiling(typeid(this).name(), __FUNCTION__)
#define END_PROFILING		sani::profiler::__privns__::endProfiling(typeid(this).name(), __FUNCTION__)

#define START_PROFILER		sani::profiler::__privns__::startProfiler(typeid(this).name(), __FUNCTION__)
#define STOP_PROFILER		sani::profiler::__privns__::stopProfiler(typeid(this).name(), __FUNCTION__)

#define PROFILER_MAKE_ROOT	sani::profiler::__privns__::makeRoot(typeid(this).name(), __FUNCTION__)

namespace sani {

	namespace profiler {

		namespace {

			ProfilerImpl impl;
		}

		/*
			TODO: should these be "hidden" or not?..
			TODO: add models when we can present them to the user.
		*/

		namespace __privns__ {

			void startProfiler(const String& module, const String& function);
			void stopProfiler(const String& module, const String& function);

			void startProfiling(const String& module, const String& function);
			void endProfiling(const String& module, const String& function);

			void makeRoot(const String& module, const String& function);
		}

		float32 rootElapsedMicroseconds();
		const String& rootFunction();
		const String& rootModule();

		const Modules& modules();
	}
}<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cmath>
#include <type_traits>

namespace MATH_NAMESPACE
{
namespace detail
{

template <typename T>
struct widen;

template <>
struct widen<int8_t>
{
    using type = int16_t;
};

template <>
struct widen<int16_t>
{
    using type = int32_t;
};

template <>
struct widen<int32_t>
{
    using type = int64_t;
};

} // detail

//-------------------------------------------------------------------------------------------------
// fixed members
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(char c)
    : rep_(rep_type(c) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(short s)
    : rep_(rep_type(s) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(int i)
    : rep_(rep_type(i) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long l)
    : rep_(rep_type(l) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long long ll)
    : rep_(rep_type(ll) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned char uc)
    : rep_(rep_type(uc) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned short us)
    : rep_(rep_type(us) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned int ui)
    : rep_(rep_type(ui) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned long ul)
    : rep_(rep_type(ul) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned long long ull)
    : rep_(rep_type(ull) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(float f)
    : rep_(f * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(double d)
    : rep_(d * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long double ld)
    : rep_(ld * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator char() const
{
    return static_cast<char>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator short() const
{
    return static_cast<short>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator int() const
{
    return static_cast<int>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long() const
{
    return static_cast<long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long long() const
{
    return static_cast<long long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned char() const
{
    return static_cast<unsigned char>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned short() const
{
    return static_cast<unsigned short>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned int() const
{
    return static_cast<unsigned int>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned long() const
{
    return static_cast<unsigned long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned long long() const
{
    return static_cast<unsigned long long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator float() const
{
    return static_cast<float>(rep_) / (rep_type(1) << F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator double() const
{
    return static_cast<double>(rep_) / (rep_type(1) << F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long double() const
{
    return static_cast<long double>(rep_) / (rep_type(1) << F);
}

//-------------------------------------------------------------------------------------------------
// Basic arithmetic
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator-(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T k = ~i;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator+(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    T k = i + j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator-(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    T k = i - j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator*(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;
    using WT = typename detail::widen<T>::type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    WT k = static_cast<WT>(i) * j >> F;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator/(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;
    using WT = typename detail::widen<T>::type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    WT k = (static_cast<WT>(i) << F) / j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

//--------------------------------------------------------------------------------------------------
// Comparisons
//

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator==(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i == j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator!=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i != j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator>(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i > j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator<(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i < j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator>=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i >= j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator<=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i <= j;
}

//-------------------------------------------------------------------------------------------------
// Math functions
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> abs(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T bits = i < 0 ? T(-1) : T(0);
    T k = (i + bits) ^ bits;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> floor(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T k = ((i >> F) << F);

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> rsqrt(fixed<I, F> const& a)
{
    static const int K = 5;
    static const fixed<I, F> threehalf = 1.5f;
    fixed<I, F> ahalf = a * fixed<I, F>(0.5f);
    fixed<I, F> t = a;

    for (int k = 0; k < K; ++k)
    {
        t = t * (threehalf - ahalf * t * t);
    }

    return t;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> sqrt(fixed<I, F> const& a)
{
    static const int K = 8;
    static const fixed<I, F> half = 0.5f;

    fixed<I, F> x = 1.0f;

    for (int k = 0; k < K; ++k)
    {
        x = half * (x + a / x);
    }

    return x;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> trunc(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T sgn = (i >> (I + F - 1)) & 1;
    T k = ((i >> F) << F) + sgn * (T(1) << F);

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

//-------------------------------------------------------------------------------------------------
// Misc.
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> select(bool k, fixed<I, F> const& a, fixed<I, F> const& b)
{
    return k ? a : b;
}

} // MATH_NAMESPACE
<commit_msg>Unnecessary include<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cmath>

namespace MATH_NAMESPACE
{
namespace detail
{

template <typename T>
struct widen;

template <>
struct widen<int8_t>
{
    using type = int16_t;
};

template <>
struct widen<int16_t>
{
    using type = int32_t;
};

template <>
struct widen<int32_t>
{
    using type = int64_t;
};

} // detail

//-------------------------------------------------------------------------------------------------
// fixed members
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(char c)
    : rep_(rep_type(c) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(short s)
    : rep_(rep_type(s) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(int i)
    : rep_(rep_type(i) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long l)
    : rep_(rep_type(l) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long long ll)
    : rep_(rep_type(ll) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned char uc)
    : rep_(rep_type(uc) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned short us)
    : rep_(rep_type(us) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned int ui)
    : rep_(rep_type(ui) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned long ul)
    : rep_(rep_type(ul) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(unsigned long long ull)
    : rep_(rep_type(ull) << F)
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(float f)
    : rep_(f * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(double d)
    : rep_(d * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::fixed(long double ld)
    : rep_(ld * (rep_type(1) << F))
{
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator char() const
{
    return static_cast<char>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator short() const
{
    return static_cast<short>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator int() const
{
    return static_cast<int>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long() const
{
    return static_cast<long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long long() const
{
    return static_cast<long long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned char() const
{
    return static_cast<unsigned char>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned short() const
{
    return static_cast<unsigned short>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned int() const
{
    return static_cast<unsigned int>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned long() const
{
    return static_cast<unsigned long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator unsigned long long() const
{
    return static_cast<unsigned long long>(rep_ >> F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator float() const
{
    return static_cast<float>(rep_) / (rep_type(1) << F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator double() const
{
    return static_cast<double>(rep_) / (rep_type(1) << F);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F>::operator long double() const
{
    return static_cast<long double>(rep_) / (rep_type(1) << F);
}

//-------------------------------------------------------------------------------------------------
// Basic arithmetic
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator-(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T k = ~i;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator+(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    T k = i + j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator-(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    T k = i - j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator*(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;
    using WT = typename detail::widen<T>::type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    WT k = static_cast<WT>(i) * j >> F;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> operator/(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;
    using WT = typename detail::widen<T>::type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    WT k = (static_cast<WT>(i) << F) / j;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

//--------------------------------------------------------------------------------------------------
// Comparisons
//

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator==(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i == j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator!=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i != j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator>(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i > j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator<(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i < j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator>=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i >= j;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline bool operator<=(fixed<I, F> const& a, fixed<I, F> const& b)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);
    T j = *reinterpret_cast<T const*>(&b);

    return i <= j;
}

//-------------------------------------------------------------------------------------------------
// Math functions
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> abs(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T bits = i < 0 ? T(-1) : T(0);
    T k = (i + bits) ^ bits;

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> floor(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T k = ((i >> F) << F);

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> rsqrt(fixed<I, F> const& a)
{
    static const int K = 5;
    static const fixed<I, F> threehalf = 1.5f;
    fixed<I, F> ahalf = a * fixed<I, F>(0.5f);
    fixed<I, F> t = a;

    for (int k = 0; k < K; ++k)
    {
        t = t * (threehalf - ahalf * t * t);
    }

    return t;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> sqrt(fixed<I, F> const& a)
{
    static const int K = 8;
    static const fixed<I, F> half = 0.5f;

    fixed<I, F> x = 1.0f;

    for (int k = 0; k < K; ++k)
    {
        x = half * (x + a / x);
    }

    return x;
}

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> trunc(fixed<I, F> const& a)
{
    using T = typename fixed<I, F>::rep_type;

    T i = *reinterpret_cast<T const*>(&a);

    T sgn = (i >> (I + F - 1)) & 1;
    T k = ((i >> F) << F) + sgn * (T(1) << F);

    return *reinterpret_cast<fixed<I, F>*>(&k);
}

//-------------------------------------------------------------------------------------------------
// Misc.
//

template <unsigned I, unsigned F>
MATH_FUNC
inline fixed<I, F> select(bool k, fixed<I, F> const& a, fixed<I, F> const& b)
{
    return k ? a : b;
}

} // MATH_NAMESPACE
<|endoftext|>


<commit_before>#include <cmath>

#include <osg/Texture2D>
#include <osg/Image>
#include <osgDB/ReadFile>

#include "Sphere.h"

// Sphere(radius, Iterationsschritte)
ph::Sphere::Sphere(const double radius, const int steps) {
    this->radius = radius;
    this->steps = steps;
    this->sphere = new Geometry;
    this->addDrawable(this->sphere.get());
    this->compute();
}

void ph::Sphere::compute() {
    this->setVerticesAndNormals();
    this->setIndicies();
}

// creating vertices / normals
void ph::Sphere::setVerticesAndNormals() {
    ref_ptr<Vec3Array> vertices = new Vec3Array();
    ref_ptr<Vec3Array> normals = new Vec3Array();
    Vec3d coords;
    double theta, phi;

    /* creating coordinates in spheric coordinates with
        x = r* cos(phi)* sin(theta); y= r* sin(phi)* sin(theta)
        z = r* cos(theta) */
    for (int i = 0; i <= this->steps; i++) {
        for (int j = 0; j < this->steps; j++) {
            theta = i * PI / this->steps;
            phi = j * 2 * PI / (this->steps-1);
            coords = Vec3d(
                radius * cos(phi) * sin(theta),
                radius * sin(phi) * sin(theta),
                radius * cos(theta)
            );
            vertices->push_back(coords);
            coords.normalize();
            normals->push_back(coords);
        }
    }

    this->sphere->setVertexArray(vertices.get());
    this->sphere->setNormalArray(normals.get());
    this->sphere->setNormalBinding(Geometry::BIND_PER_VERTEX);
}

// creating indices radial from bottom to top
void ph::Sphere::setIndicies() {
    ref_ptr<DrawElementsUInt> indices = new DrawElementsUInt(GL_TRIANGLE_STRIP);

    for (int i = 0; i < this->steps; i++) {
        for (int j = 0; j <= this->steps; j++) {
            indices->push_back((i * this->steps + j % this->steps));
            indices->push_back(((i + 1) * this->steps) + (j % this->steps));
        }
    }

    this->sphere->addPrimitiveSet(indices.get());
}

// creating texture coordinates
void ph::Sphere::setTextureCoordinates(int textureNumber) {
    ref_ptr<Vec2Array> texcoords = new Vec2Array;

    for (double j = this->steps; j >= 0; j--) {
        for (double i = 0; i < this->steps; i++) {
            texcoords->push_back(Vec2d(i/this->steps, j/this->steps));
        }
    }

    this->sphere->setTexCoordArray(textureNumber, texcoords.get());
}

// setting texture on sphere
void ph::Sphere::setTexture(const int textureNumber, const string filename) {
    this->setTextureCoordinates(textureNumber);

    ref_ptr<Texture2D> texture = new Texture2D;
    ref_ptr<Image> image = osgDB::readImageFile(filename);
    texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE);
    texture->setImage(image.get());
    this->getOrCreateStateSet()->setTextureAttributeAndModes(textureNumber, texture.get());
}
<commit_msg>adding culling to sphere<commit_after>#include <cmath>

#include <osg/Texture2D>
#include <osg/Image>
#include <osgDB/ReadFile>
#include <osg/CullFace>

#include "Sphere.h"

// Sphere(radius, Iterationsschritte)
ph::Sphere::Sphere(const double radius, const int steps) {
    this->radius = radius;
    this->steps = steps;
    this->sphere = new Geometry;
    this->addDrawable(this->sphere.get());
    this->compute();
}

void ph::Sphere::compute() {
    this->setVerticesAndNormals();
    this->setIndicies();
}

// creating vertices / normals
void ph::Sphere::setVerticesAndNormals() {
    ref_ptr<Vec3Array> vertices = new Vec3Array();
    ref_ptr<Vec3Array> normals = new Vec3Array();
    Vec3d coords;
    double theta, phi;

    /* creating coordinates in spheric coordinates with
        x = r* cos(phi)* sin(theta); y= r* sin(phi)* sin(theta)
        z = r* cos(theta) */
    for (int i = 0; i <= this->steps; i++) {
        for (int j = 0; j < this->steps; j++) {
            theta = i * PI / this->steps;
            phi = j * 2 * PI / (this->steps-1);
            coords = Vec3d(
                radius * cos(phi) * sin(theta),
                radius * sin(phi) * sin(theta),
                radius * cos(theta)
            );
            vertices->push_back(coords);
            coords.normalize();
            normals->push_back(coords);
        }
    }

    this->sphere->setVertexArray(vertices.get());
    this->sphere->setNormalArray(normals.get());
    this->sphere->setNormalBinding(Geometry::BIND_PER_VERTEX);
}

// creating indices radial from bottom to top
void ph::Sphere::setIndicies() {
    ref_ptr<DrawElementsUInt> indices = new DrawElementsUInt(GL_TRIANGLE_STRIP);

    for (int i = 0; i < this->steps; i++) {
        for (int j = 0; j <= this->steps; j++) {
            indices->push_back((i * this->steps + j % this->steps));
            indices->push_back(((i + 1) * this->steps) + (j % this->steps));
        }
    }

    this->sphere->addPrimitiveSet(indices.get());
}

// creating texture coordinates
void ph::Sphere::setTextureCoordinates(int textureNumber) {
    ref_ptr<Vec2Array> texcoords = new Vec2Array;

    for (double j = this->steps; j >= 0; j--) {
        for (double i = 0; i < this->steps; i++) {
            texcoords->push_back(Vec2d(i/this->steps, j/this->steps));
        }
    }

    this->sphere->setTexCoordArray(textureNumber, texcoords.get());
}

// setting texture on sphere
void ph::Sphere::setTexture(const int textureNumber, const string filename) {
    this->setTextureCoordinates(textureNumber);

    ref_ptr<Texture2D> texture = new Texture2D;
    ref_ptr<Image> image = osgDB::readImageFile(filename);
    texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE);
    texture->setImage(image.get());
    this->getOrCreateStateSet()->setTextureAttributeAndModes(textureNumber, texture.get());
    ref_ptr<CullFace> cull = new CullFace;
    // Effect is instant traveling through the planet; BACK = no texture if u are inside the sphere
    cull->setMode(CullFace::FRONT);
    this->getOrCreateStateSet()->setAttributeAndModes(cull.get());
}
<|endoftext|>


<commit_before>#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/Geometry>
#include <osg/MatrixTransform>

#include <osgUtil/Tesselator>
#include <osgUtil/TransformCallback>

#include <osgText/Text>

#include <osgGA/TrackballManipulator>

#include <osgGLUT/Viewer>
#include <osgGLUT/glut>

#include <osgDB/ReadFile>

//#include "CreateShadowedScene.h"

osg::Geometry* createWing(const osg::Vec3& left, const osg::Vec3& nose, const osg::Vec3& right,float chordRatio,const osg::Vec4& color)
{
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3 normal = (nose-right)^(left-nose);
    normal.normalize();

    osg::Vec3 left_to_right = right-left;
    osg::Vec3 mid = (right+left)*0.5f;
    osg::Vec3 mid_to_nose = (nose-mid)*chordRatio*0.5f;

    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(left);
    //vertices->push_back(mid+mid_to_nose);

    unsigned int noSteps = 40;
    for(unsigned int i=1;i<noSteps;++i)
    {
        float ratio = (float)i/(float)noSteps;
        vertices->push_back(left + left_to_right*ratio + mid_to_nose* (cosf((ratio-0.5f)*osg::PI*2.0f)+1.0f));
    }

    vertices->push_back(right);
    vertices->push_back(nose);

    geom->setVertexArray(vertices);

    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(normal);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(color);
    geom->setColorArray(colors);
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,vertices->getNumElements()));

    osgUtil::Tesselator tesselator;
    tesselator.retesselatePolygons(*geom);

    return geom;

}

osg:: Node* createTextBelow(const osg::BoundingBox& bb)
{
    osg::Geode* geode = osgNew osg::Geode();

    osgText::PolygonFont*   polygonFont= osgNew  osgText::PolygonFont("fonts/times.ttf",20, 3);
    osgText::Text*          text = osgNew  osgText::Text(polygonFont);

    text->setText("OpenSceneGraph");
    text->setAlignment(osgText::Text::CENTER_CENTER);
    text->setAxisAlignment(osgText::Text::XZ_PLANE);
    text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
    text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
    osg::StateSet* stateset = text->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

    geode->addDrawable( text );

    return geode;
}

osg:: Node* createTextLeft(const osg::BoundingBox& bb)
{
    osg::Geode* geode = osgNew osg::Geode();

    osgText::PolygonFont*   polygonFont= osgNew  osgText::PolygonFont("fonts/times.ttf",100, 3);
    osgText::Text*          text = osgNew  osgText::Text(polygonFont);

    text->setText("OpenSceneGraph");
    text->setAlignment(osgText::Text::RIGHT_CENTER);
    text->setAxisAlignment(osgText::Text::XZ_PLANE);
    text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.2f));
    text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
    osg::StateSet* stateset = text->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

    geode->addDrawable( text );
    return geode;
}

osg:: Node* createGlobe(const osg::BoundingBox& bb,float ratio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::StateSet* stateset = osgNew osg::StateSet();

    osg::Image* image = osgDB::readImageFile("land_shallow_topo_2048.jpg");
    if (image)
    {
	osg::Texture2D* texture = osgNew osg::Texture2D;
	texture->setImage(image);
	texture->setMaxAnisotropy(8);
	stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
    }

    geode->setStateSet( stateset );

    // the globe
    geode->addDrawable(new osg::ShapeDrawable(osgNew osg::Sphere(bb.center(),bb.radius()*ratio)));

    osg::MatrixTransform* xform = new osg::MatrixTransform;
    xform->setAppCallback(new osgUtil::TransformCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(30.0f)));
    xform->addChild(geode);

    return xform;
}

osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));

    // back faces
    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));

    return geode;
}

osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));

    // back faces
    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));

    return geode;
}

osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
    osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
    osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));

    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));

    return geode;
}

osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
{

    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3 normal = (corner-top)^(right-corner);
    normal.normalize();

    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(top);
    vertices->push_back(corner);
    vertices->push_back(right);
    vertices->push_back(right+(top-corner));

    geom->setVertexArray(vertices);

    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(normal);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));

    osg::Geode* geode = osgNew osg::Geode();
    geode->addDrawable(geom);

    return geode;
}

osg::Node* createLogo()
{
    osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
    float chordRatio = 0.5f;
    float sphereRatio = 0.6f;

    // create a group to hold the whole model.
    osg::Group* logo_group = new osg::Group;

    // create a transform to orientate the box and globe.
    osg::MatrixTransform* xform = new osg::MatrixTransform;
    xform->setDataVariance(osg::Object::STATIC);
    xform->setMatrix(osg::Matrix::translate(-bb.center())*
                     osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
                     osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
                     osg::Matrix::translate(bb.center()));

    // add the box and globe to it.
    //xform->addChild(createBox(bb,chordRatio));
    //xform->addChild(createBoxNo5(bb,chordRatio));
    xform->addChild(createBoxNo5No2(bb,chordRatio));
    // add the transform to the group.
    logo_group->addChild(xform);

    logo_group->addChild(createGlobe(bb,sphereRatio));

    // add the text to the group.
    //group->addChild(createTextBelow(bb));
    logo_group->addChild(createTextLeft(bb));

    // create the backdrop to render the shadow to.
    osg::Vec3 corner(-800.0f,150.0f,-100.0f);
    osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
    osg::Vec3 right(1000.0f,0.0f,0.0f); right += corner;

    osg::Group* backdrop = new osg::Group;
    backdrop->addChild(createBackdrop(corner,top,right));

    //osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
    //osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);

    osg::Group* scene = new osg::Group;
    scene->addChild(logo_group);
    scene->addChild(backdrop);

    return scene;
}

int main( int argc, char **argv )
{

    glutInit( &argc, argv );

    // create the commandline args.
    std::vector<std::string> commandLine;
    for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);

    // create the viewer and the model to it.
    osgGLUT::Viewer viewer;

    viewer.setWindowTitle(argv[0]);

    // configure the viewer from the commandline arguments, and eat any
    // parameters that have been matched.
    viewer.readCommandLine(commandLine);

    osg::Node* node = createLogo();

    // add model to viewer.
    viewer.addViewport( node );

    // register trackball maniupulators.
    viewer.registerCameraManipulator(osgNew osgGA::TrackballManipulator);

    viewer.open();

    viewer.run();

    return 0;
}
<commit_msg>Changed the colour of the text to be the same as the OpenGL logo.<commit_after>#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/Geometry>
#include <osg/MatrixTransform>

#include <osgUtil/Tesselator>
#include <osgUtil/TransformCallback>

#include <osgText/Text>

#include <osgGA/TrackballManipulator>

#include <osgGLUT/Viewer>
#include <osgGLUT/glut>

#include <osgDB/ReadFile>

//#include "CreateShadowedScene.h"

osg::Geometry* createWing(const osg::Vec3& left, const osg::Vec3& nose, const osg::Vec3& right,float chordRatio,const osg::Vec4& color)
{
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3 normal = (nose-right)^(left-nose);
    normal.normalize();

    osg::Vec3 left_to_right = right-left;
    osg::Vec3 mid = (right+left)*0.5f;
    osg::Vec3 mid_to_nose = (nose-mid)*chordRatio*0.5f;

    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(left);
    //vertices->push_back(mid+mid_to_nose);

    unsigned int noSteps = 40;
    for(unsigned int i=1;i<noSteps;++i)
    {
        float ratio = (float)i/(float)noSteps;
        vertices->push_back(left + left_to_right*ratio + mid_to_nose* (cosf((ratio-0.5f)*osg::PI*2.0f)+1.0f));
    }

    vertices->push_back(right);
    vertices->push_back(nose);

    geom->setVertexArray(vertices);

    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(normal);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(color);
    geom->setColorArray(colors);
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,vertices->getNumElements()));

    osgUtil::Tesselator tesselator;
    tesselator.retesselatePolygons(*geom);

    return geom;

}

osg:: Node* createTextBelow(const osg::BoundingBox& bb)
{
    osg::Geode* geode = osgNew osg::Geode();

    osgText::PolygonFont*   polygonFont= osgNew  osgText::PolygonFont("fonts/times.ttf",20, 3);
    osgText::Text*          text = osgNew  osgText::Text(polygonFont);

    text->setText("OpenSceneGraph");
    text->setAlignment(osgText::Text::CENTER_CENTER);
    text->setAxisAlignment(osgText::Text::XZ_PLANE);
    text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
    text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
    osg::StateSet* stateset = text->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

    geode->addDrawable( text );

    return geode;
}

osg:: Node* createTextLeft(const osg::BoundingBox& bb)
{
    osg::Geode* geode = osgNew osg::Geode();

    osgText::PolygonFont*   polygonFont= osgNew  osgText::PolygonFont("fonts/times.ttf",100, 3);
    osgText::Text*          text = osgNew  osgText::Text(polygonFont);

    text->setText("OpenSceneGraph");
    text->setAlignment(osgText::Text::RIGHT_CENTER);
    text->setAxisAlignment(osgText::Text::XZ_PLANE);
    text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.2f));
    //text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's orignal OSG colour
    text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
    osg::StateSet* stateset = text->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

    geode->addDrawable( text );
    return geode;
}

osg:: Node* createGlobe(const osg::BoundingBox& bb,float ratio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::StateSet* stateset = osgNew osg::StateSet();

    osg::Image* image = osgDB::readImageFile("land_shallow_topo_2048.jpg");
    if (image)
    {
	osg::Texture2D* texture = osgNew osg::Texture2D;
	texture->setImage(image);
	texture->setMaxAnisotropy(8);
	stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
    }

    geode->setStateSet( stateset );

    // the globe
    geode->addDrawable(new osg::ShapeDrawable(osgNew osg::Sphere(bb.center(),bb.radius()*ratio)));

    osg::MatrixTransform* xform = new osg::MatrixTransform;
    xform->setAppCallback(new osgUtil::TransformCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(30.0f)));
    xform->addChild(geode);

    return xform;
}

osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));

    // back faces
    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));

    return geode;
}

osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));

    // back faces
    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));

    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));

    return geode;
}

osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
{
    osg::Geode* geode = osgNew osg::Geode();

    osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
    osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
    osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);

    // front faces.
    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));

    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));

    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));

    return geode;
}

osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
{

    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3 normal = (corner-top)^(right-corner);
    normal.normalize();

    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(top);
    vertices->push_back(corner);
    vertices->push_back(right);
    vertices->push_back(right+(top-corner));

    geom->setVertexArray(vertices);

    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(normal);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));

    osg::Geode* geode = osgNew osg::Geode();
    geode->addDrawable(geom);

    return geode;
}

osg::Node* createLogo()
{
    osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
    float chordRatio = 0.5f;
    float sphereRatio = 0.6f;

    // create a group to hold the whole model.
    osg::Group* logo_group = new osg::Group;

    // create a transform to orientate the box and globe.
    osg::MatrixTransform* xform = new osg::MatrixTransform;
    xform->setDataVariance(osg::Object::STATIC);
    xform->setMatrix(osg::Matrix::translate(-bb.center())*
                     osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
                     osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
                     osg::Matrix::translate(bb.center()));

    // add the box and globe to it.
    //xform->addChild(createBox(bb,chordRatio));
    //xform->addChild(createBoxNo5(bb,chordRatio));
    xform->addChild(createBoxNo5No2(bb,chordRatio));
    // add the transform to the group.
    logo_group->addChild(xform);

    logo_group->addChild(createGlobe(bb,sphereRatio));

    // add the text to the group.
    //group->addChild(createTextBelow(bb));
    logo_group->addChild(createTextLeft(bb));

    // create the backdrop to render the shadow to.
    osg::Vec3 corner(-800.0f,150.0f,-100.0f);
    osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
    osg::Vec3 right(1000.0f,0.0f,0.0f); right += corner;

    osg::Group* backdrop = new osg::Group;
    backdrop->addChild(createBackdrop(corner,top,right));

    //osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
    //osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);

    osg::Group* scene = new osg::Group;
    scene->addChild(logo_group);
    scene->addChild(backdrop);

    return scene;
}

int main( int argc, char **argv )
{

    glutInit( &argc, argv );

    // create the commandline args.
    std::vector<std::string> commandLine;
    for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);

    // create the viewer and the model to it.
    osgGLUT::Viewer viewer;

    viewer.setWindowTitle(argv[0]);

    // configure the viewer from the commandline arguments, and eat any
    // parameters that have been matched.
    viewer.readCommandLine(commandLine);

    osg::Node* node = createLogo();

    // add model to viewer.
    viewer.addViewport( node );

    // register trackball maniupulators.
    viewer.registerCameraManipulator(osgNew osgGA::TrackballManipulator);

    viewer.open();

    viewer.run();

    return 0;
}
<|endoftext|>