Skip to content

**** ****

for my bad memories..

OpenGL로 CAE-Pre 프로그램을 만든지 언 2년째..

2022-01-13


처음 2년전에 OpenGL을 시작했을때가 생각난다.

OpenGL은 배우기 어렵고 너무 많은 시간을 소비해야 한다는 글들을 보고 이게 과연 옳은 방향일까 고민을 했었다.
막상 긴 시간동안 오픈소스 엔진을 찾아보니 CAE 프로그램을 만드는데 전혀 적합하지 않다는 것을 알았다.
맞다. 저런 엔진은 게임을 만들려는 사람들에 국한된 얘기구나.. 하는 결론을 내렸다.

전혀 무지한 상태에서 그래도 자신있다는 Tcl/Tk로 GUI를 만들고
Tk 프레임에 glfw를 이용해서 OpenGL 프레임을 붙여서 개발을 먼저 시작했는데,
아무래도 UI가 느리다 보니 제약이 많아졌다.

그래서 또 자신있는 Qt를 메인 GUI로 하고 Qt내부에 패널을 두어서 Tk 프로그램을 유저가 추가할 수 있도록 했다.
추가된 Tk 패널에는 Tk로 GUI를 짜고 Tcl로 스크립팅도 가능하게하여 자동화도 염두해 두었다.

정말 난관은 요소 주변에 edge를 그리는거였다.
단순히 라인으로 그리는건 정말 안이쁘고 여러 가지 문제가 많았다.
그래서 One Pass 와이어프레임 랜더링 기법의 논문을 찾아서 구현을 했다.
이걸 구현했을때는 참으로 기뻤다.

투명 기법도 꽤 긴 시간 적절한 방법을 찾아서 적용도 했다.
이것 역시 만들고 나니 뿌뜻했다.

정말 엔진 없이 생 OpenGL로 개발 하려니 처음부터 모든걸 작성해줘야 한다는걸 지금도 실감하고 있다..

당연한 얘기지만 Pre의 기본 기능인
요소의 피킹에 있어서 다양한 방법으로 선택할 수 있는 기능이 있어야 했다.
역시 다양한 문제야 봉착했고 이런 문제를 해결하기 위한 알고리즘들을 찾아보고
적절한 방법을 테스트후 마우스로의 픽킹 부터 영역 선택등 다양한 방법을 구현했다.
또 선택된 요소에 적절한 색을 지정하는 방법도 필요하기에 구현했다.

제일 문제는 메시 구조체 였다.
메시 구초체는 이웃 요소를 빠르게 쉽게 찾을 수 있어야 했고,
요소 삭제시 연결 무결성이 유지가 되어야했다. 또 적절한 메모리를 소요해야한다.
아직까진 상용 Pre 프로그램과 비슷한 정도의 메모리를 차지한다. (앞으로는 더 늘수도 있겠지..)

요소 마스킹 기능도 구현했다. (아직까진 속도면에서 못마땅한데 좀더 다른 방법을 고안해냐야겠다)

캐드 기능은 아직도 엄두가 안나는데 아직까진 OCC 를 이용해서 iges나 step 정도를 뷰잉 해주는 수준이다.

LS-Dyna의 인풋덱, 또 결과 파일인 d3plot, binout 을 보는 기능도 구현했다.
역시 에니메이션도 된다. 이 부분은 아직 추가할 기능이 산적히 싸여있다.

OpenGL 멀티 윈도우는 Qt로 작업했더니 아주 쉽게 지원이 되었다.

쓸말은 많지만.. 여기까지.. 이제 자야겠다.


STEP 파일 로딩 기능 추가

2021-12-15


자작 CAE Pre 프로그램을 만드는 중인데..
OpenCASCADE 를 이용하여 STEP/IGES 파일 로딩 기능 추가를 해보았음.
Geometry 편집이나 간단한 Primitive 추가 기능을 넣어야 하는데..
먼저 Shape 구조체를 정리해야 할 것 같음..
머리가 정리가 안된 상태라.. 어렵네..


ntldd

2021-11-04


msys2 내에서 gcc 로 컴파일된 파일의 depedency 가 걸린 dll 파일 조사 프로그램

% pacman -Sy mingw-w64-x86_64-ntldd-git
% ntldd -R ./main.exe

결과는..

	lsreader_c-vc142-0_1.dll (0x000001c800de0000)
	 libiomp5md.dll (0x000001c801b90000)
	 libmmd.dll (0x000001c8022e0000)
	 MSVCP140.dll => C:\Windows\SYSTEM32\MSVCP140.dll (0x000001c801b90000)
	 imagehlp.dll => C:\Windows\SYSTEM32\imagehlp.dll (0x000001c801b90000)
	  dbghelp.dll => C:\Windows\SYSTEM32\dbghelp.dll (0x000001c801d50000)
	 VCRUNTIME140.dll => C:\Windows\SYSTEM32\VCRUNTIME140.dll (0x000001c801c20000)
	 VCRUNTIME140_1.dll => C:\Windows\SYSTEM32\VCRUNTIME140_1.dll (0x000001c801c20000)
	libassimp.dll => D:\MSYS2\mingw64\bin\libassimp.dll (0x000001c8022e0000)
	 libminizip-1.dll => D:\MSYS2\mingw64\bin\libminizip-1.dll (0x000001c800de0000)
	  ADVAPI32.dll => C:\Windows\SYSTEM32\ADVAPI32.dll (0x000001c800e10000)
	   SECHOST.dll => C:\Windows\SYSTEM32\SECHOST.dll (0x000001c800ec0000)
	    USERENV.dll => C:\Windows\SYSTEM32\USERENV.dll (0x000001c800f60000)
	     netutils.dll => C:\Windows\SYSTEM32\netutils.dll (0x000001c800f90000)
	     logoncli.dll => C:\Windows\SYSTEM32\logoncli.dll (0x000001c800f90000)
	      WLDAP32.dll => C:\Windows\SYSTEM32\WLDAP32.dll (0x000001c800fd0000)
	       DSPARSE.dll => C:\Windows\SYSTEM32\DSPARSE.dll (0x000001c801020000)
	      ext-ms-win-smbshare-browserclient-l1-1-0.dll => not found
	     profapi.dll => C:\Windows\SYSTEM32\profapi.dll (0x000001c801180000)
	      ext-ms-win-profile-extender-l1-1-0.dll => not found
	     ext-ms-win-profile-userenv-l1-1-0.dll => not found
.....

윈도우즈10 마우스/키보드 끊김 현상

2021-10-08


Windows7에서 10 에서는 전력 설정 항목이 추가되면서 저전력 모드로 자동으로 바뀌게 되는 경우가 있음.
이 저전력 모드 때문에 마우스 / 키보드 프리징 현상이 발생할 수 있음.

저전력 모드 끄기

1. 키보드의 Windows Key + X 버튼을 누름.
2. Windows Powershell(관리자) 버튼 클릭 하여 파워쉘을 실행.
3. bcdedit /set disabledynamictick yes 입력

이후 Windows 10 재부팅을 하시면 저전력 모드가 해지가 됨.
특히 Laptop 사용자에게 발생되는 프리징 현상은 저전력 문제일 확률이 매우 높음..


OpenGL + Mesh + CAD 표시

2021-09-17


사실 오랫동안 이것저것 CAD 파일을 OpenGL로 뿌려주는 기능을 구현중이었음.

이것저것 코드 분석해보고.. (흠.. CAD 관련 코드가 그리 많지않음)
테스트하고.. 짬짬히 알아보느라 시간이 한달정도 걸린것 같음.

어쨌건 현재 쓸 수 있는 오픈소스중 OpenCASCADE 만한게 없는것 같음.
처음엔 꽤 괜찮아 보이는 OpenCASCADE의 기본 Viewer를 내 프로그램에 내장시켜볼까
코드도 뜯어보고.. 해봤는데.. 이건 답이 안나옴..
왜냐하면 내 프로그램은 Mesh 와 CAD를 둘다 표시해줘야하기 때문에.. 결국 포기함.

그래서 Mesh 표시 기능은 구현했고.. 여기에 CAD 표시 기능만 추가해야겠단 생각이 들어서
처음엔 nurbs 형태로 뿌려줄까해서 다른 코드들도 좀 보고 했는데.. 이것도 도저히 아닌것 같아서..
OpenCASCADE의 BRepMesh_IncrementalMesh 를 사용해서 CAD를 매시를 치고..
이걸 매시 형태로 불러들여 보여줌. 여기에 smooth shading 를 적용하니 꽤 그럴싸함.

근데 아무래도 기본 BRepMesh_IncrementalMesh 이 클래스 자체가 매시를 그리 잘 쳐주는게 아님..
결국 매시 기능만 돈 주고 사야하나… 에효…
어쩐지 Express Mesh 라는 콤포넌트를 팔더라니.. (https://www.opencascade.com/components/express-mesh-component/)

암튼 아래는 이것저것 step, iges 파일을 읽어들인 화면.


투명으로 바꿔봄


꽤 큰 파일도 불러와봄


OpenCASCADE topology

2021-09-14


출처: https://dev.opencascade.org/content/exploring-compound

OpenCASCADE의 topology는 다음과 같음.

아래와 같이 탐색.

MainWindow::MainWindow(QMainWindow *parent):QMainWindow(parent)
{
    //! ---------
    //! a viewer
    //! ---------
    occViewPort aViewer = new occViewPort(this);
    if(aViewer->getContext().IsNull()) aViewer->init();
    this->setCentralWidget(aViewer);

    //! ------------------------
    //! load the file from disk
    //! ------------------------
    STEPControl_Reader aReader;
    IFSelect_ReturnStatus stat = aReader.ReadFile(FILENAME);

    if(stat!=IFSelect_RetDone) exit(1);

    aReader.TransferRoots();
    TopoDS_Shape aShape = aReader.OneShape();

    //! ----------------
    //! list of shapes
    //! ----------------
    QList<TopoDS_Shape> csolids;
    QList<TopoDS_Shape> solids;
    QList<TopoDS_Shape> wires;
    QList<TopoDS_Shape> edges;
    QList<TopoDS_Shape> shells;
    QList<TopoDS_Shape> faces;

    for(TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next())
    {
        const TopoDS_Shape &curShape = anIt.Value();
        TopAbs_ShapeEnum type = curShape.ShapeType();

        if(type==TopAbs_COMPOUND)
        {
            cout<<"____COMPOUND____"<<endl;

            TopoDS_Builder aShellBuilder;
            TopoDS_Shell aShell;

            TopoDS_Builder aWireBuilder;
            TopoDS_Wire aWire;

            aShellBuilder.MakeShell(aShell);
            aWireBuilder.MakeWire(aWire);

            int faceCount = 0;
            int edgeCount = 0;

            for(TopoDS_Iterator anExp(curShape); anExp.More(); anExp.Next())
            {
                const TopoDS_Shape &curShape1 = anExp.Value();
                TopAbs_ShapeEnum type1 = curShape1.ShapeType();

                if(type1==TopAbs_SHELL)
                {
                    for(TopExp_Explorer anExp(curShape1,TopAbs_FACE);anExp.More();anExp.Next())
                    {
                        const TopoDS_Shape &curShape2 = anExp.Current();
                        aShellBuilder.Add(aShell,curShape2);
                        faceCount++;
                    }
                }

                if(type1==TopAbs_EDGE)
                {
                    aWireBuilder.Add(aWire,curShape1);
                    edgeCount++;
                }
            }

            if(faceCount>1) shells<<aShell;
            if(edgeCount>1) wires<<aWire;
            else if(edgeCount==1)
            {
                //! --------------------------------------
                //! remove "aWire" from the list of wires
                //! --------------------------------------
                wires.removeOne(aWire);
                for(TopExp_Explorer anExp(aWire,TopAbs_EDGE); anExp.More(); anExp.Next())
                {
                    const TopoDS_Shape &curEdge = anExp.Current();
                    edges<<curEdge;
                }
            }
        }

        //! -----------------
        //! composite solids
        //! -----------------
        if(type==TopAbs_COMPSOLID)
        {
            cout<<"____COMPSOLID____"<<endl;
            csolids<<curShape;
        }

        //! -------
        //! solids
        //! -------
        if(type==TopAbs_SOLID)
        {
            solids<<curShape;
        }

        //! ------
        //! faces
        //! ------
        if(type==TopAbs_SHELL)
        {
            for(TopExp_Explorer anExp(curShape,TopAbs_FACE);anExp.More();anExp.Next())
            {
                const TopoDS_Shape &curShape1 = anExp.Current();
                faces<<curShape1;
            }
        }
    }

    cout<<"____Nb solids: "<<solids.length()<<"____"<<endl;
    cout<<"____Nb shells: "<<shells.length()<<"____"<<endl;
    cout<<"____Nb faces: "<<faces.length()<<"____"<<endl;
    cout<<"____Nb wires: "<<wires.length()<<"____"<<endl;
    cout<<"____Nb edges: "<<edges.length()<<"____"<<endl;

    //! --------
    //! display
    //! --------
    QList<TopoDS_Shape> listOfShapes;
    listOfShapes<<csolids<<solids<<shells<<faces<<wires<<edges;
    for(int i=0; i<listOfShapes.length(); i++)
    {
        const Handle(AIS_Shape) &anAIS_Shape = new AIS_Shape(listOfShapes.at(i));
        aViewer->getContext()->Display(anAIS_Shape,AIS_Shaded,-1,true,false);
    }
    aViewer->FitAll();
    aViewer->setAction3D_Rotation();
}

It gives

____Nb solids: 1____
____Nb shells: 2____
____Nb faces: 1____
____Nb wires: 1____
____Nb edges: 1____

for file 000000000_mixed_1

and

____Nb solids: 1____
____Nb shells: 1____
____Nb faces: 3____
____Nb wires: 1____
____Nb edges: 1____

for 000000000_mixed_2.stp

sample.zip


CentOS 6.5 repository 변경

2021-09-11


CentOS 6.x 버전의 업데이트는 2020.11.30 일부로 종료됨.

$ yum repolist
Loaded plugins: fastestmirror, refresh-packagekit, security
Determining fastest mirrors
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
 Eg. Invalid release/repo/arch combination/
removing mirrorlist with no valid mirrors: /var/cache/yum/x86_64/6/base/mirrorlist.txt
repo id                        repo name                                  status
base                           CentOS-6 - Base                            0
extras                         CentOS-6 - Extras                          0
updates                        CentOS-6 - Updates                         0
repolist: 0

종료된 버전의 경우 CentOS는 따로 vault 업데이트 서버를 운영중임.
해당 서버로 아래와 같이 CentOS-Base.repo 파일의 전체 내용을 변경하면 업데이트 가능.

$ cd /etc/yum.repos.d/
$ cp CentOS-Base.repo CentOS-Base.repo.old

$ vim CentOS-Base.repo (아래의 내용으로 교체)

[base]
name=CentOS-$releasever - Base
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
baseurl=https://vault.centos.org/6.10/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

# released updates
[updates]
name=CentOS-$releasever - Updates
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
baseurl=https://vault.centos.org/6.10/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

# additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
# baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
baseurl=https://vault.centos.org/6.10/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

$ yum clean all

$ yum repolist
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
repo id                        repo name                                  status
base                           CentOS-6 - Base                            6,713
extras                         CentOS-6 - Extras                             47
updates                        CentOS-6 - Updates                         1,193
repolist: 7,953